Bagaimana cara menyalin beberapa, tetapi tidak semua file?

54

Jadi, Anda dapat menggunakan *sebagai kartu liar untuk semua file saat menggunakan cpdalam konteks direktori. Apakah ada cara untuk menyalin semua file kecuali xfile?

Chad Harrison
sumber

Jawaban:

42

Di dalam bashAnda dapat menggunakan extglob:

 $ shopt -s extglob  # to enable extglob
 $ cp !(b*) new_dir/

di mana !(b*)mengecualikan semua b*file.

Anda nanti dapat menonaktifkan extglobdengan

 $ shopt -u extglob
buru-buru
sumber
Apakah Anda tahu jika ada sesuatu yang setara dengan shell tcsh?
Levon
Sayangnya saya tidak. Sepertinya findadalah satu-satunya cara di tcsh:find . -maxdepth 1 ! -name "exclude*" -exec cp -t destination {} \+
buru
50

Rsync menangani ini dengan baik.

Contoh salin semua: rsync -aP /folder1/* /folder/2

Contoh salin semua dengan pengecualian: rsync -aP --exclude=x /folder1/* /folder2/

The -aPswitch:

a: Mirip dengan cp -a, rekursif, dll. P: Menampilkan kemajuan, fitur bagus dari rsync.

Tim
sumber
5
Dan lihat jawaban ini untuk panduan singkat ke daftar pengecualian rsync umum.
Gilles 'SANGAT berhenti menjadi jahat'
1
Di darwin / MacOS, gunakan -rPalih-alih -aPjika Anda ingin berulang. -aadalah untuk pengarsipan. Tidak yakin apakah ini berubah atau hanya berbeda pada MacOS.
jpoveda
rsyncmemang memiliki opsi untuk membuatnya rekursif. Contoh: rsync --recursive -P --exclude=x /folder1/* /folder2/. (Diuji hanya pada Ubuntu)
n1k31t4
12

Ini bukan fitur dari cp, itu fitur shell Anda (itu memperluas *berarti semua file non-dot), jadi jawabannya tergantung pada shell yang Anda gunakan. Misalnya, zshmendukung sintaks ini:

$ cp ^x /path/to/destination

Dimana ^xartinya "semua file kecuali x"

Anda juga dapat menggabungkan pola seleksi dan de-seleksi, misalnya untuk menyalin semua file wav kecuali yang mengandung xyz, Anda dapat menggunakan:

cp *.wav~*xyz*
Michael Mrozek
sumber
Ada komentar bash?
Chad Harrison
@ hidroparadise Saya tidak tahu banyak tentang bash, tetapi jawaban ini sepertinya menutupinya
Michael Mrozek
Bagaimana dengan tcsh? Adakah yang tahu
Levon
4

Dapat juga dilakukan dalam shell bourne biasa (portabel / kompatibel) dalam berbagai cara dengan alat standar dalam cara yang jauh lebih elegan daripada menggunakan globbing shell canggih atau perintah dengan opsi built-in-exclusion.

Jika tidak ada terlalu banyak file (dan tidak dengan nama termasuk spasi dan / atau linebreak), ini bisa menjadi caranya:

cp `ls | egrep -v '^excludename$'` destdir/.

Tentu, bashdan alat-alat GNU hebat dan kuat, tetapi mereka tidak selalu tersedia. Jika Anda bermaksud memasukkannya ke dalam skrip portabel, saya akan merekomendasikan findseperti dalam komentar oleh Rush.

MattBianco
sumber
2
Saya menemukan bahwa bagian terakhir dari jawaban Anda hanya mengalihkan perhatian dari topik yang sedang dibahas. Selain itu, "Unix" bukan standar emas lagi (jika pernah ada). Hanya saja tidak relevan jika ada sesuatu yang "Unix" atau tidak lagi, meskipun judul situs ini adalah "Unix dan Linux".
Alexander
2
BAIK. Saya memindahkan komentar ke sini: Unix bukan GNU. Saya setuju bahwa "keanehan" sesuatu tidak terlalu menarik, tetapi saya masih percaya pada portabilitas dan mengetahui sedikit tentang sejarah Anda.
MattBianco
Sepenuhnya setuju dengan Anda di sana.
Alexander
2

Jika Anda ingin menyalin semua yang ada di folder (termasuk subfolder) ke sub-direktori tertentu:

cp -R $(ls | grep -v '^subdir$') subdir/

Bekerja dengan sh, bash, zsh (setidaknya).

pengguna2707671
sumber
1
Meyakinkan saya ini bukan niat yang sama dengancp -R * subdir/
roaima
1
Jika Anda menggunakan perintah "cp -R * subdir /", bash / zsh mencoba menyalin 'subdir' secara rekursif. Anda berakhir dengan kesalahan: "nama terlalu panjang (tidak disalin)".
user2707671
Poin bagus. Saran Anda berusaha menghindari peringatan dari cp(bukan dari bash/ sh), " cp: cannot copy a directory, ‘subdir’, into itself, ‘subdir/subdir’". Salinan tidak lengkap dengan benar. Sayangnya varian Anda rusak dengan nama file yang mengandung tanda baca spasi atau shell-sensitive. Lihat unix.stackexchange.com/q/128985/135943
roaima
-1

extglob adalah cara terbaik sejauh ini kurasa.

Cara lain menggunakan cp $(ls --ignore=x) subdir/

Edwin Lee
sumber
Ini akan berhenti mengingat bentuk karakter khusus apa pun dalam nama file. (Spasi, baris baru, $dll.) Jangan pernah parsing output dari ls. unix.stackexchange.com/q/128985/135943
Wildcard