Linux: Salin semua pola pencocokan file dari dir dan subdir ke dalam satu dir

31

Jika saya ingin menyalin semua *.sofile dari srcke dstsaya akan lakukan:

cp src/*.so dst

Namun, saya ingin menyalin semua *.sofile dari src dan subdirs itu ke dalam dst. Ada petunjuk?

Albus Dumbledore
sumber

Jawaban:

36

Mencoba:

find src/ -type f | grep -i so$ | xargs -i cp {} dst
Mike Insch
sumber
17
finddapat melakukan pencocokan pola dan menjalankan perintah. Tidak perlu menyalurkan outputnya:find src/ -type f -name '*.so' -exec cp '{}' dst/ ';'
jáquer
1
Ya, itu bisa, namun seringkali lebih mudah untuk membaca pipeline, juga kemampuan pencocokan pola grepjauh melebihi pola shell sederhana yang digunakan dalam -nameparameter find. xargsjuga jauh lebih kuat daripada -execparameter untuk find.
Mike Insch
2
Solusi @jaquer jauh lebih baik karena pada MacOSX xargs utility tidak memiliki opsi -i. Tapi solusinya bekerja seperti pesona.
bialix
Saya kesulitan dengan pesan kesalahan pada argumen -i ke xargs sampai saya membaca komentar dari @bialix mengenai solusi jaquer, yang bekerja dengan baik di Mac saya. Terima kasih
svannoy
Apakah ini akan membuat subdirektori sesuai kebutuhan?
Lennart Rolland
15

Jika Anda menggunakan Bash, Anda dapat mengaktifkan globstar opsi shell untuk mencocokkan file dan direktori secara rekursif:

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

Jika Anda perlu menemukan file yang namanya dimulai dengan ., dan / atau file di dalam dan di bawah direktori yang namanya dimulai ., tetapkan dotglobjuga opsi (misalnya dengan shopt -s dotglob). Anda dapat mengatur keduanya dalam satu perintah:

shopt -s globstar dotglob
Jacquer
sumber
Tidak menyalin file dalam subdirektori yang dimulai dengan a. dalam nama mereka
rboy
8

Saya mencoba perintah yang disarankan oleh Mike:

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

tetapi berakhir dengan membuang semua file ke direktori dstdengan jalur relatif mereka hilang.

Untuk menjaga path relatif, perintah perlu dimodifikasi untuk ini:

find src/ -type f | grep -i so$ | xargs -i cp {} dst/{}
Ilya Druker
sumber
7
+1. Namun, ini mengasumsikan bahwa direktori yang sesuai dengan jalur sumber relatif ada di bawah dst. Jika tidak, gunakan cp --parents. Juga, pastikan untuk mengutip nama file. Jadi: ... | xargs -i cp --parents "{}" dst(perhatikan bahwa argumen terakhir cpadalah "hanya" direktori tujuan). Perintah dapat dibuat lebih pendek (dan mungkin lebih cepat) menggunakan -tbendera: ... | xargs cp --parents -t dst.
Stephan202
1
@ Stephan202 Saya harus menggunakan... | xargs cp {} --parents -t dst.
warvariuc
bagi mereka yang menggunakan mac, --parentstidak tersedia. Saya menggunakan dittotempatnya: stackoverflow.com/questions/11246070/cp-parents-option-on-mac
Bryan Young
3

Cara lain untuk melakukan ini adalah seperti ini:

find src/ -type f -name "*.so" -exec cp {} dst/ \;
Kyriakos
sumber
Dan ini harus mengurangi jumlah cpproses: ... -exec cp -t dst/ {} +.
Kamil Maciorowski
Hai Kamil! Terima kasih atas komentarnya! Bisakah Anda jelaskan bagaimana solusi Anda membuat segalanya lebih cepat! Selalu bersedia untuk belajar lebih banyak :)
Kyriakos
Ketika Anda berakhir -execdengan ;, {}digantikan oleh satu jalur pada suatu waktu. Anda mendapatkan terpisah cpuntuk setiap file. Dengan +sintaks finddiganti {}dengan beberapa hasil (hingga batas panjang baris perintah yang ditentukan sistem; pembatasan: {}harus menjadi hal terakhir sebelumnya +, karenanya cp -t). Menciptakan dan mengakhiri suatu proses adalah hal yang relatif mahal. Untuk alasan ini, ada baiknya digunakan +kapan saja Anda mengharapkan banyak hasil. Dalam hal ini, menyalin banyak file mungkin memerlukan banyak waktu sehingga perbedaannya dapat berlalu tanpa diketahui; namun itu praktik yang baik.
Kamil Maciorowski
1

Grep dapat diganti dengan menggunakan find's -name :

find src/ -type f -name "*.so" | xargs -i cp {} dst/{}
Th. Thielemann
sumber