Skopiuj wszystkie pliki z określonym rozszerzeniem ze wszystkich podkatalogów

112

W systemie unix chcę skopiować wszystkie pliki z określonym rozszerzeniem (wszystkie pliki programu Excel) ze wszystkich podkatalogów do innego katalogu. Mam następujące polecenie:

cp --parents `find -name \*.xls*` /target_directory/

Problemy z tym poleceniem to:

  • Kopiuje również strukturę katalogów, a ja chcę tylko pliki (więc wszystkie pliki powinny trafić do / target_directory /)

  • Nie kopiuje plików ze spacjami w nazwach plików (których jest sporo)

Jakieś rozwiązania tych problemów?

Abdel
źródło
O co chodzi find... exec mv?
fedorqui 'SO przestać szkodzić'

Odpowiedzi:

174

--parents kopiuje strukturę katalogów, więc powinieneś się tego pozbyć.

Sposób, w jaki to napisałeś, findwykonuje, a dane wyjściowe są umieszczane w wierszu poleceń w taki sposób, że cpnie można odróżnić spacji oddzielających nazwy plików od spacji w nazwie pliku. Lepiej zrobić coś takiego

$ find . -name \*.xls -exec cp {} newDir \;

w którym cpjest wykonywany dla każdej findznalezionej nazwy pliku i poprawnie przekazuje nazwę pliku. Oto więcej informacji na temat tej techniki.

Zamiast tego możesz użyć zsh i po prostu wpisać

$ cp **/*.xls target_directory

zsh może rozwinąć symbole wieloznaczne, aby uwzględnić podkatalogi, co bardzo ułatwia tego rodzaju czynności.

Brian Agnew
źródło
2
Tak. „bin it” oznacza wyrzucenie go. Teraz poprawione :-)
Brian Agnew
13
Bash4.0+, a ksh93także obsługuje **. W przypadku basha użyj, shopt -s globstaraby go włączyć. Dla ksh to set -Glub set -o globstar.
pynexj
2
@Daryl - uzupełniłem dalej. Ale odpowiedź została już oznaczona jako „zaakceptowana”, uwaga
Brian Agnew
5
Ten exec jest technicznie mniej wydajny niż przechodzenie do xargs, który zrobi to wszystko w jak najmniejszej find . -name '*.xls' -print0 | xargs -0 cp -t destdir
liczbie
2
@BrianAgnew Och, na pewno dobrze jest mieć w komentarzach dodatkowe informacje dla krnąbrnych pracowników Google.
Taywee
37

Z powyższego wymyśliłem tę wersję. Ta wersja działa również dla mnie w terminalu odzyskiwania mac.

find ./ -name '*.xsl' -exec cp -prv '{}' '/path/to/targetDir/' ';'

Będzie szukał plików z rozszerzeniem xsl w bieżącym katalogu i rekurencyjnie we wszystkich podkatalogach. Skopiuje je wszystkie do katalogu docelowego.

flagi cp to:

  • p - zachowaj atrybuty pliku
  • r - rekurencyjny
  • v - gadatliwy (pokazuje, co jest kopiowane)
guya
źródło
1
To jest to samo, co musiałem zrobić, gdy SSH wszedł do Bluehost.
Plummer
4
NIE zachowuje podkatalogów.
b005t3r
3
@ b005t3r, czyli zgodnie z projektem, nie powinno. Taka była cała intencja pytania PO. Chciał, aby wszystkie pliki z podkatalogów zostały skopiowane do jednego katalogu bez podkatalogów
Madivad
2
Czy istnieje sposób, aby to zmienić, aby zachować podkatalogi?
Matthew Dean
8

Miałem podobny problem. Rozwiązałem to używając:

find dir_name '*.mp3' -exec cp -vuni '{}' "../dest_dir" ";"

Program '{}'i ";"wykonuje kopię każdego pliku.

stingMantis
źródło
3

Sam też musiałem to zrobić. Zrobiłem to za pomocą argumentu --parents dla cp:

find SOURCEPATH -name filename*.txt -exec cp --parents {} DESTPATH \;
Ten facet
źródło
1
find [SOURCEPATH] -type f -name '[PATTERN]' | 
    while read P; do cp --parents "$P" [DEST]; done

możesz usunąć opcję --parents, ale istnieje ryzyko kolizji, jeśli wiele plików ma tę samą nazwę.

Camion
źródło