Przenieś wszystkie pliki z określonym rozszerzeniem z wielu podkatalogów do jednego katalogu


43

Mam kilka plików .zip w kilku katalogach:

Fol1/Fol2
Fol3
Fol4/Fol5

Jak mam przenieść je wszystkie do wspólnego folderu podstawowego?


Czy chcesz zachować strukturę katalogów? Chcesz przenieść katalogi, czy tylko pliki zip?
Jordan

Chcę tylko przenieść pliki zip. Nie dbam o katalogi - można je zostawić w spokoju lub usunąć.
InquilineKea,

Odpowiedzi:


55

Przejdź do katalogu najwyższego poziomu drzewa zawierającego pliki zip ( cd …), a następnie uruchom

mv **/*.zip /path/to/single/target/directory

Działa to natychmiast po wyjęciu z pudełka. Jeśli twoja powłoka jest bash, musisz shopt -s globstarnajpierw uruchomić (możesz i powinieneś umieścić to polecenie w swoim ~/.bashrc). Jeśli twoją powłoką jest ksh, musisz uruchomić set -o globstarnajpierw (włóż ją do swojego ~/.kshrc).

Alternatywnie, użyj find, który działa wszędzie bez specjalnego przygotowania, ale jest bardziej skomplikowany:

find . -name '*.zip' -exec mv {} /path/to/single/target/directory \;

Jeśli chcesz później usunąć puste katalogi, w zsh:

rmdir **/*(/^Fod)

W bash lub ksh:

rmdir **/*/

i powtarzaj tak długo, jak są puste katalogi do usunięcia. Alternatywnie, w dowolnej powłoce

find . -depth -type d -empty -exec rmdir {} \;

Pierwsze findpolecenie powyżej działało w bashu, ale musiało się zmienić na find . -nameetc, aby działało.
JeffThompson

1
@Jeff .jest domyślny dla GNU find, ale nie dla innych, dodałem go jawnie.
Gilles „SO- przestań być zły”

13

Jeśli chcesz tylko przenieść .zippliki, możesz zrobić coś takiego

mkdir ./zipfiles
find . -name "*.zip" -exec mv "{}" ./zipfiles \;

3

Jeśli używasz bash w wersji 4 lub wyższej lub zsh , możesz także użyć globowania rekurencyjnego:

mv **/*.zip /path/to/move/zip/files/to

To przeniesie TYLKO pliki, a nie ich ścieżki względne, więc mogą wystąpić kolizje.


co rozumiesz przez ścieżki względne?
Kunok

2

Ten jest bezpieczny przy przenoszeniu danych i bezbłędnie, co obsługuje większość dystrybucji niezależnie od wersji. To polecenie skanuje podkatalogi, a następnie przenosi lub kopiuje do nowego katalogu docelowego.

find . -name *.flac -exec mv '{}' "./flac/" ";"
  • Uruchom to polecenie w głównym katalogu, który zawiera podkatalogi z plikami, które chcesz przenieść.
  • Gdzie możesz zmienić *.flacna coś takiego jak *.zipw twoim przypadku. Lub *.doctylko każde rozszerzenie działa.
  • i mvjest poleceniem do przenoszenia plików, lub możesz użyć cpdo skopiowania danych zamiast przenoszenia.
  • ./flac/to katalog docelowy, do którego chcę przenieść wszystkie pliki FLAC. Możesz także nadać mu pełną ścieżkę/home/myid/flac/

Pełny przykład. (w tym przypadku istnieje wiele podkatalogów z nazwą wykonawcy muzyki na, /home/myid/Music/a pliki FLAC znajdują się na różnych poziomach podkatalogów. Ponieważ nie potrzebuję folderów wykonawców, ale chcę mieć wszystkie pliki FLAC w jednym katalogu na/home/myid/Music/flac/

cd /home/myid/Music
mkdir flac
find . -name *.flac -exec mv '{}' "./flac/" ";"
cd flac
ls

Następnie wyświetli wszystkie pliki FLAC.


Co ma ;zrobić?
Francesco Boi

@FrancescoBoi należy poczekać, aż polecenie bash w tym samym wierszu zakończy pracę. a następnie przejdź do następnego wiersza poleceń bash. Jest to przydatne w przypadku poleceń zawierających skrypty, takie jak .pl lub python, ponieważ bash po prostu uruchomi go, a następnie przejdzie do następnego wiersza, więc dla bezpieczeństwa używam; po poleceniach, które wymagają czasu lub skryptu, na wypadek, gdyby bash je pomija.
Seandex,

0

Jako hack bash możesz wykorzystać moc tar:

(cd origin/;find . -exec file --mime-type "{}" \;|grep "application/zip"|cut -d ':' -f 1|xargs tar cf -)|(cd target/; tar xf -) && rm -fr origin/

Ma to tę zaletę, że nie zależy od rozszerzeń plików, ponieważ używa filepolecenia do wyboru plików do przeniesienia i zachowuje strukturę katalogów, ale nie działa ze ścieżkami zawierającymi spacje.

Ostatnim rmjest tylko usunięcie oryginalnych plików (ponieważ @InquilineKea mówi, że nie dba o oryginalny folder w komentarzu).

Oczywiście jest to szczególnie odpowiednie, jeśli folder źródłowy / docelowy / znajdują się na różnych dyskach. W przeciwnym razie inne proponowane rozwiązania są bardziej wydajne (nawet jeśli opierają się na konwencjach nazewnictwa, a nie na filetreści).


0

Zakładając, że masz wersje GNU find i mv, poniższe będą bardziej wydajne niż istniejące odpowiedzi oparte na znalezieniu:

find . -name '*.zip' -exec mv --target-directory='/path/to/outputdir' '{}' +

Użycie a +na końcu find -exec oznacza, że ​​lista plików zostanie przekazana do komendy mv, zamiast wykonywania jednej komendy mv na znaleziony plik. Ograniczeniem tego jest jednak to, że można umieścić „{}” tylko na końcu polecenia, co wymaga użycia opcji mv --target-directory i, o ile wiem, jest to GNU-ism.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.