Bagaimana cara menggunakan perintah 'cp' untuk mengecualikan direktori tertentu?
411
Saya ingin menyalin semua file dalam direktori kecuali beberapa file dalam sub-direktori tertentu. Saya perhatikan bahwa perintah 'cp' tidak memiliki opsi --exclude. Jadi, bagaimana saya bisa mencapai ini?
Perhatikan bahwa opsi dir thefoldertoexcludesetelah --excluderelatif terhadap sourcefolder, yaitu sourcefolder/thefoldertoexclude,.
Anda juga dapat menambahkan -nuntuk menjalankan kering untuk melihat apa yang akan disalin sebelum melakukan operasi nyata, dan jika semuanya ok, hapus -ndari baris perintah.
Setuju, Anda tidak bisa mengalahkan kesederhanaan dan kekuatan--exclude
Matthew Wilcoxson
31
adalah thefoldertoexcluderelatif ke sourcefolderatau direktori kerja saat ini? terima kasih
Beebee
46
Ini relatif ke folder sumber. Ini akan mengecualikan sumber folder / .git agar tidak disalin. rsync -r --exclude target sumber '.git'
orkoden
15
Mungkin saya salah, tetapi saya pikir ini praktik yang baik untuk menambahkan "switch" sebelum "parameter". Juga halaman manual laporan rsync --exclude dapat digunakan seperti dengan sintaks "=" atau tanpa. Jadi untuk standarisasi di seluruh sistem operasi, saya akan menggunakan rsync -av --progress --exclude="thefoldertoexclude" sourcefolder /destinationfolder- tetap upvote untuk rsync daripada menemukan, karena Anda dapat dengan mudah menggunakan jalur absolut untuk sumber sementara dalam menemukan itu lebih sulit karena menggunakan {}di dst.
Xavi Montero
1
@mamun Tentu saja misalnya dari server jarak jauh ke mesin lokal: $ rsync [email protected]:/var/www/mypage /var/www/mylocalpage/atau dari lokal ke jarak jauh$ rsync /var/www/mylocalpage/ [email protected]:/var/www/mypage
sobi3ch
84
Nah, jika pengecualian pola nama file tertentu harus dilakukan oleh setiap utilitas file unix-ish (seperti cp, mv, rm, tar, rsync, scp, ...), duplikasi usaha yang sangat besar akan terjadi. Sebaliknya, hal-hal seperti itu dapat dilakukan sebagai bagian dari globbing , yaitu dengan shell Anda.
Jadi Anda hanya memasukkan pola di dalamnya !(), dan meniadakan pertandingan. Polanya bisa rumit secara arbitrer, mulai dari penghitungan jalur individu (seperti yang ditunjukkan Vanwaril dalam jawaban lain):, !(filename1|path2|etc3)hingga hal-hal yang mirip dengan regex dengan bintang dan kelas karakter. Lihat halaman manual untuk detailnya.
Saya pikir Anda perlu -pathargumen untuk menguji hierarki jalur, bukan -nama
James Murty
3
Dan Anda juga akan memerlukan titik koma di akhir:find . -type f -not -path '*/not-from-here/*' -exec cp '{}' '/dest/{}' \;
Matthew Wilcoxson
1
Wow, tidak akan membiarkan saya: "Editan harus setidaknya 6 karakter"!
Matthew Wilcoxson
1
@MatthewWilcoxson Meh. Batasan-batasan itu akan dicabut, segera setelah Anda memperoleh lebih banyak perwakilan. Saya mengedit jawabannya. Terima kasih lagi!
Linus Kleen
1
@ Kenapa tidak rsync? Karena mungkin tidak ada dalam sistem! sementara find, cpselalu ada di tempat mereka. Atau Anda dari jenis cowok, yang memasang 2 gram barang untuk melakukan hal-hal sederhana?
Membuat fungsi shell yang menyederhanakan penggunaan untuk jalur sumber khusus dan mengecualikan hanya satu file atau direktori: # $1 = source path # $2 = destination path # $3 = filter copy_from_source_to_destination_except_filter() { cp -r $(ls -A $1 | grep -v -w $3 | awk -v path=$1 '{printf "%s/%s ", path, $1}') $2 }
ElectRocnic
gagal dengan direktori dengan spasi
Sérgio
27
Cara termudah yang saya temukan, di mana Anda dapat menyalin semua file tidak termasuk file dan folder hanya dengan menambahkan nama mereka di dalam tanda kurung:
Anda dapat melewati ekstra lsdan cukup lakukan cp !(file1|file1) dest.
Shawn Chin
Jangan gunakan -laR. itu menambahkan string yang mengganggu cp. cp $(ls folder/!exclude_folder0|exclude_folder1)) dest
LAL
5
Opsi lain yang lebih sederhana adalah menginstal dan menggunakan rsync yang memiliki opsi --exclude-dir, dan dapat digunakan untuk file lokal dan jarak jauh.
rsyncsebenarnya cukup rumit. harus melakukan beberapa tes untuk membuatnya berfungsi.
Katakanlah Anda ingin menyalin /var/www/htmlke /var/www/devtapi perlu mengecualikan/var/www/html/site/video/ direktori mungkin karena ukurannya. Perintahnya adalah:
Slash terakhir /pada sumber diperlukan, jika tidak, salin juga akan menyalin direktori sumber daripada isinya dan menjadi /var/www/dev/html/xxxx, yang mungkin bukan yang Anda inginkan.
The para --excludepath adalah relatif ke sumber langsung. Bahkan jika Anda meletakkan jalur absolut penuh, itu tidak akan berhasil.
-vadalah untuk verbose, -aadalah untuk mode arsip yang berarti Anda ingin rekursi dan ingin mempertahankan hampir semuanya.
Ini adalah modifikasi dari jawaban Linus Kleen. Jawabannya tidak berhasil untuk saya karena akan ada. ditambahkan di depan path file yang tidak disukai cp (path akan terlihat seperti source / .destination / file).
Tidak cantik mungkin - tetapi ini adalah satu-satunya pilihan yang saya temukan di sini yang bekerja dengan cpdan shell POSIX standar seperti sh.
tomekwi
1
Jawaban ini secara dramatis diremehkan. Ini adalah jawaban yang paling kompatibel, paling mudah dibaca dan mudah dipahami. Kudos, saya tidak tahu mengapa saya tidak memikirkannya.
Robert Talada
Terima kasih @RobertTalada, seberapa jauh jawabannya dari sekarang? ️🌈
lama12345
0
Saya menggunakan loop "do while" untuk membaca output dari perintah find. Dalam contoh ini, saya mencocokkan (daripada mengecualikan) pola tertentu karena ada jumlah pencocokan pola yang lebih terbatas yang saya inginkan daripada yang tidak saya inginkan. Anda bisa membalikkan logika dengan -tidak di depan flag -iname:
Saya menggunakan hal di atas untuk menyalin semua file jenis musik yang lebih baru di server saya daripada file di Western Digital TV Live Hub yang telah saya pasang di / media / wd. Saya menggunakan hal di atas karena saya memiliki banyak file DVD, mpegs, dll. Saya ingin mengecualikan DAN karena untuk beberapa alasan rsync sepertinya sedang menyalin, tetapi setelah saya melihat perangkat wd, file tidak ada walaupun tidak ada kesalahan selama rsync dengan perintah ini:
Bagian pertama lssemua file tetapi menyembunyikan file tertentu dengan flag -I. Output dari lsdigunakan sebagai input standar untuk bagian kedua. xargsmembangun dan menjalankan perintah cp -rf -t destdirdari input standar. bendera -rberarti menyalin direktori secara rekursif, -fberarti menyalin file secara paksa yang akan menimpa file dalam destdir, -tmenentukan salinan direktori tujuan.
tar -c | tar -x
?Jawaban:
rsync cepat dan mudah:
Anda dapat menggunakan
--exclude
beberapa kali.Perhatikan bahwa opsi dir
thefoldertoexclude
setelah--exclude
relatif terhadapsourcefolder
, yaitusourcefolder/thefoldertoexclude
,.Anda juga dapat menambahkan
-n
untuk menjalankan kering untuk melihat apa yang akan disalin sebelum melakukan operasi nyata, dan jika semuanya ok, hapus-n
dari baris perintah.sumber
--exclude
thefoldertoexclude
relatif kesourcefolder
atau direktori kerja saat ini? terima kasihrsync -av --progress --exclude="thefoldertoexclude" sourcefolder /destinationfolder
- tetap upvote untuk rsync daripada menemukan, karena Anda dapat dengan mudah menggunakan jalur absolut untuk sumber sementara dalam menemukan itu lebih sulit karena menggunakan{}
di dst.$ rsync [email protected]:/var/www/mypage /var/www/mylocalpage/
atau dari lokal ke jarak jauh$ rsync /var/www/mylocalpage/ [email protected]:/var/www/mypage
Nah, jika pengecualian pola nama file tertentu harus dilakukan oleh setiap utilitas file unix-ish (seperti cp, mv, rm, tar, rsync, scp, ...), duplikasi usaha yang sangat besar akan terjadi. Sebaliknya, hal-hal seperti itu dapat dilakukan sebagai bagian dari globbing , yaitu dengan shell Anda.
pesta
man 1 bash
, / extglob .Contoh:
Jadi Anda hanya memasukkan pola di dalamnya
!()
, dan meniadakan pertandingan. Polanya bisa rumit secara arbitrer, mulai dari penghitungan jalur individu (seperti yang ditunjukkan Vanwaril dalam jawaban lain):,!(filename1|path2|etc3)
hingga hal-hal yang mirip dengan regex dengan bintang dan kelas karakter. Lihat halaman manual untuk detailnya.zsh
man 1 zshexpn
, / nama file generasi .Anda dapat melakukan
setopt KSH_GLOB
dan menggunakan pola bash-like. Atau,Jadi
x~y
cocok dengan polax
, tetapi tidak termasuk polay
. Sekali lagi, untuk detail selengkapnya, lihat halaman manual.ikan baru!
The ikan shell memiliki banyak jawaban cantik ini:
Bonus pro-tip
Ketik
cp *
, tekan CtrlX*dan lihat apa yang terjadi. itu tidak berbahaya, aku janjisumber
zsh
.setopt -u extglob
.Mengapa menggunakan
rsync
ketika Anda bisa melakukan:Ini mengasumsikan struktur direktori target sama dengan sumbernya.
sumber
-path
argumen untuk menguji hierarki jalur, bukan -namafind . -type f -not -path '*/not-from-here/*' -exec cp '{}' '/dest/{}' \;
rsync
? Karena mungkin tidak ada dalam sistem! sementarafind
,cp
selalu ada di tempat mereka. Atau Anda dari jenis cowok, yang memasang 2 gram barang untuk melakukan hal-hal sederhana?sumber
# $1 = source path # $2 = destination path # $3 = filter copy_from_source_to_destination_except_filter() { cp -r $(ls -A $1 | grep -v -w $3 | awk -v path=$1 '{printf "%s/%s ", path, $1}') $2 }
Cara termudah yang saya temukan, di mana Anda dapat menyalin semua file tidak termasuk file dan folder hanya dengan menambahkan nama mereka di dalam tanda kurung:
sumber
-bash: !: event not found
Memperluas komentar mvds , ini bekerja untuk saya
sumber
Ini relatif terhadap direktori sumber.
Ini akan mengecualikan direktori
source/.git
dari disalin.sumber
rsync
dan pertama coba dengan opsi -n untuk melihat apa yang akan disalin
sumber
Saya menganggap Anda menggunakan bash atau dash. Apakah ini akan berhasil?
Melakukan ls mengecualikan file yang tidak Anda inginkan, dan menggunakannya sebagai argumen pertama untuk cp
sumber
ls
dan cukup lakukancp !(file1|file1) dest
.cp $(ls folder/!exclude_folder0|exclude_folder1)) dest
Opsi lain yang lebih sederhana adalah menginstal dan menggunakan rsync yang memiliki opsi --exclude-dir, dan dapat digunakan untuk file lokal dan jarak jauh.
sumber
rsync
sebenarnya cukup rumit. harus melakukan beberapa tes untuk membuatnya berfungsi.Katakanlah Anda ingin menyalin
/var/www/html
ke/var/www/dev
tapi perlu mengecualikan/var/www/html/site/video/
direktori mungkin karena ukurannya. Perintahnya adalah:rsync -av --exclude 'sites/video' /var/www/html/ /var/www/dev
Beberapa peringatan :
/
pada sumber diperlukan, jika tidak, salin juga akan menyalin direktori sumber daripada isinya dan menjadi/var/www/dev/html/xxxx
, yang mungkin bukan yang Anda inginkan.The para
--exclude
path adalah relatif ke sumber langsung. Bahkan jika Anda meletakkan jalur absolut penuh, itu tidak akan berhasil.-v
adalah untuk verbose,-a
adalah untuk mode arsip yang berarti Anda ingin rekursi dan ingin mempertahankan hampir semuanya.sumber
Sunting: lupa untuk mengecualikan jalur target juga (kalau tidak itu akan menyalin secara rekursif).
sumber
Ini adalah modifikasi dari jawaban Linus Kleen. Jawabannya tidak berhasil untuk saya karena akan ada. ditambahkan di depan path file yang tidak disukai cp (path akan terlihat seperti source / .destination / file).
Perintah ini bekerja untuk saya:
find . -type f -not -path '*/exlude-path/*' -exec cp --parents '{}' '/destination/' \;
perintah --parents menjaga struktur direktori.
sumber
sumber
Hanya memindahkannya sementara ke direktori tersembunyi (dan ganti namanya setelah, jika diinginkan).
sumber
cp
dan shell POSIX standar sepertish
.Saya menggunakan loop "do while" untuk membaca output dari perintah find. Dalam contoh ini, saya mencocokkan (daripada mengecualikan) pola tertentu karena ada jumlah pencocokan pola yang lebih terbatas yang saya inginkan daripada yang tidak saya inginkan. Anda bisa membalikkan logika dengan -tidak di depan flag -iname:
Saya menggunakan hal di atas untuk menyalin semua file jenis musik yang lebih baru di server saya daripada file di Western Digital TV Live Hub yang telah saya pasang di / media / wd. Saya menggunakan hal di atas karena saya memiliki banyak file DVD, mpegs, dll. Saya ingin mengecualikan DAN karena untuk beberapa alasan rsync sepertinya sedang menyalin, tetapi setelah saya melihat perangkat wd, file tidak ada walaupun tidak ada kesalahan selama rsync dengan perintah ini:
sumber
Bagian pertama
ls
semua file tetapi menyembunyikan file tertentu dengan flag-I
. Output darils
digunakan sebagai input standar untuk bagian kedua.xargs
membangun dan menjalankan perintahcp -rf -t destdir
dari input standar. bendera-r
berarti menyalin direktori secara rekursif,-f
berarti menyalin file secara paksa yang akan menimpa file dalamdestdir
,-t
menentukan salinan direktori tujuan.sumber
cp -r
ls -A | grep -v "Excluded_File_or_folder"
../$target_location -vsumber