Linux: Skopiuj wszystkie pliki pasujące do wzorca z katalogu i podkatalogów do jednego katalogu


31

Gdybym chciał, aby skopiować wszystkie *.sopliki srcdo dstzrobiłbym:

cp src/*.so dst

Chcę jednak skopiować wszystkie *.sopliki z src i jego podkatalogów do dst. Jakieś wskazówki?

Odpowiedzi:


36

Próbować:

find src/ -type f | grep -i so$ | xargs -i cp {} dst

17
findPotrafi dopasowywać wzorce i wykonywać polecenia. Nie trzeba przesyłać danych wyjściowych:find src/ -type f -name '*.so' -exec cp '{}' dst/ ';'
jáquer

1
Tak, może jednak, choć często łatwiej jest odczytać potok, również możliwości dopasowania wzorca grepznacznie przewyższają proste wzorce powłoki używane w -nameparametrze do find. xargsjest również znacznie potężniejszy niż -execparametr do find.
Mike Insch,

2
Rozwiązanie @jaquer jest znacznie lepsze, ponieważ na MacOSX narzędzie xargs nie ma opcji -i. Ale jego rozwiązanie działa jak urok.
bialix,

Walczyłem z komunikatem o błędzie w argumencie -i do xargs, dopóki nie przeczytałem komentarza @bialix dotyczącego rozwiązania jaquera, które działało idealnie na moim Macu. Dzięki
svannoy,

Czy utworzy to podkatalogi w razie potrzeby?
Lennart Rolland

15

Jeśli używasz Bash, możesz włączyć globstar opcję powłoki, aby rekurencyjnie dopasowywać pliki i katalogi:

shopt -s globstar
cp src/**/*.so dst

Jeśli chcesz znaleźć pliki, których nazwy zaczynają się od ., i / lub pliki w i pod katalogami, których nazwy zaczynają się od ., ustaw dotglobrównież opcję (np. Z shopt -s dotglob). Możesz ustawić je oba za pomocą jednego polecenia:

shopt -s globstar dotglob

Nie kopiuje plików w podkatalogach zaczynających się od. w ich imieniu
rboy

8

Wypróbowałem polecenie sugerowane przez Mike'a:

find src/ -type f | grep -i so$ | xargs -i cp {} dst

ale skończyło się to zrzuceniem wszystkich plików do katalogu dstz utratą ich ścieżek względnych.

Aby zachować ścieżki względne, polecenie należy zmodyfikować w następujący sposób:

find src/ -type f | grep -i so$ | xargs -i cp {} dst/{}

7
+1. Zakłada się jednak, że katalogi odpowiadające względnym ścieżkom źródłowym istnieją pod dst. Jeśli tak nie jest, użyj cp --parents. Pamiętaj też, aby podać nazwy plików. Zatem: ... | xargs -i cp --parents "{}" dst(zauważ, że ostatnim argumentem cpjest teraz „tylko” katalog docelowy). Polecenie może być wykonane nawet krótszy (i prawdopodobnie szybciej) przy użyciu -tflagi: ... | xargs cp --parents -t dst.
Stephan202

1
@ Stephan202 Musiałem użyć... | xargs cp {} --parents -t dst.
warvariuc

dla tych na komputerze Mac --parentsnie jest dostępny. Użyłem dittozamiast niego: stackoverflow.com/questions/11246070/cp-parents-option-on-mac
Bryan Young,

3

Kolejny sposób to zrobić:

find src/ -type f -name "*.so" -exec cp {} dst/ \;

I to powinno zmniejszyć liczbę cpprocesów: ... -exec cp -t dst/ {} +.
Kamil Maciorowski

Hej Kamil! Dziękuje za komentarz! Czy możesz mi wyjaśnić, w jaki sposób Twoje rozwiązanie przyspiesza działanie! Zawsze chętny, aby dowiedzieć się więcej :)
Kyriakos,

Kiedy kończy -execsię ;, {}otrzymuje jedną ścieżkę naraz. Dostajesz osobny cpdla każdego pliku. Z +składniowych findreplaces {}z wieloma wynikami (do granicy systemowej zdefiniowanej długości linii poleceń ograniczeń: {}musi być ostatnią rzeczą przed +, stąd cp -t). Tworzenie i kończenie procesu jest względnie kosztowne. Z tego powodu warto go używać, +gdy oczekuje się wielu wyników. W takim przypadku kopiowanie dużej liczby plików i tak może zająć dużo czasu, więc różnica może minąć niezauważona; niemniej jednak jest to dobra praktyka.
Kamil Maciorowski

1

Grep można zastąpić za pomocą polecenia find's -name :

find src/ -type f -name "*.so" | xargs -i cp {} dst/{}
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.