Salin folder secara rekursif, tidak termasuk beberapa folder
197
Saya mencoba menulis skrip bash sederhana yang akan menyalin seluruh isi folder termasuk file dan folder tersembunyi ke folder lain, tetapi saya ingin mengecualikan folder tertentu. Bagaimana saya bisa mencapai ini?
Saya membayangkan sesuatu seperti menemukan. -nama * disalurkan ke grep / v "exclude-pattern" untuk memfilter yang tidak Anda inginkan dan kemudian disalurkan ke cp untuk melakukan penyalinan.
i_am_jorf
1
Saya mencoba melakukan sesuatu seperti itu, tetapi tidak bisa menemukan cara menggunakan cp dengan pipa
trobrock
1
Ini mungkin harus pergi ke pengguna super. Perintah yang Anda cari adalah xargs. Anda juga bisa melakukan sesuatu seperti dua tar yang dihubungkan oleh pipa.
Kyle Butt
1
Mungkin sudah terlambat dan tidak menjawab pertanyaan dengan akurat, tetapi inilah tipnya: Jika Anda ingin mengecualikan hanya anak-anak langsung dari direktori, Anda dapat memanfaatkan pencocokan pola bash, misalnyacp -R !(dir1|dir2) path/to/destination
Boris D. Teoharov
1
Perhatikan bahwa !(dir1|dir2)polanya extglobharus dinyalakan ( shopt -s extglobuntuk mengaktifkannya).
Perhatikan bahwa menggunakan sourcedan source/berbeda. Garis miring berarti menyalin isi folder sourceke dalamnya destination. Tanpa trailing slash, itu berarti menyalin folder sourceke dalamnya destination.
Atau, jika Anda memiliki banyak direktori (atau file) untuk dikecualikan, Anda dapat menggunakan --exclude-from=FILE, di mana FILEnama file yang berisi file atau direktori untuk dikecualikan.
--exclude mungkin juga berisi wildcard, seperti --exclude=*/.svn*
Saya sarankan untuk menambahkan --dry-run untuk memeriksa file mana yang akan disalin.
loretoparisi
1
@AmokHuginnsson - Sistem apa yang Anda gunakan? Rsync disertakan secara default di semua distro Linux arus utama yang saya ketahui, termasuk RHEL, CentOS, Debian, dan Ubuntu, dan saya percaya itu ada di FreeBSD juga.
siliconrockstar
1
Untuk distro yang diturunkan RHEL: yum install rsync, atau pada rilis berbasis Debian: apt-get install rsync. Kecuali jika Anda membangun server Anda dari basis absolut pada perangkat keras Anda sendiri, ini bukan masalah. rsync diinstal secara default di kotak Amazon EC2 saya, juga dan kotak saya dari ZeroLag dan RackSpace.
siliconrockstar
2
rsync tampaknya sangat lambat dibandingkan dengan cp? Setidaknya ini pengalaman saya.
Kojo
2
Misalnya untuk mengabaikan dir git:rsync -av --exclude='.git/' ../old-repo/ .
nycynik
40
Gunakan tar bersama dengan pipa.
cd /source_directory
tar cf ---exclude=dir_to_exclude .|(cd /destination && tar xvf -)
Pendekatan ini pertama-tama tidak perlu menguji sumber target (dan mengecualikan direktori tertentu dalam arsip) dan kemudian menguraikannya pada target. Tidak direkomendasikan!
Wouter Donders
4
@Waldheri kamu salah. Ini solusi terbaik. Itu tidak persis apa yang diminta OP dan bekerja pada instalasi default sebagian besar * nix seperti OS. Taring dan untaring dilakukan dengan cepat tanpa artefak sistem file (dalam memori), biaya tar + untar ini dapat diabaikan.
AmokHuginnsson
@WouterDonders Tar adalah overhead minimal. Itu tidak menerapkan kompresi.
Kyle Butt
9
Anda dapat menggunakan finddengan -prunepilihan.
Contoh dari man find:
cd / source-dir
Temukan . -name .snapshot -prune -o \ (\! -name * ~ -print0 \) |
cpio -pmd0 / dest-dir
Perintah ini menyalin isi / source-dir ke / dest-dir, tetapi mengabaikan
file dan direktori bernama .snapshot (dan apa pun di dalamnya). Juga
menghilangkan file atau direktori yang namanya berakhir ~, tetapi tidak
tenda. Konstruk -prune -o \ (... -print0 \) cukup umum. Itu
ide di sini adalah bahwa ekspresi sebelum-cocok cocok dengan hal-hal yang
untuk dipangkas. Namun, aksi -prune itu sendiri mengembalikan true, jadi
mengikuti -o memastikan bahwa sisi kanan dievaluasi hanya untuk
direktori-direktori yang tidak dipangkas (isi dari pemangkasan)
direktori bahkan tidak dikunjungi, jadi isinya tidak relevan).
Ekspresi di sisi kanan -o hanya dalam tanda kurung
untuk kejelasan. Ini menekankan bahwa tindakan -print0 hanya terjadi
untuk hal-hal yang tidak memiliki -prune diterapkan padanya. Karena
kondisi `dan 'default di antara tes mengikat lebih erat dari -o, ini
memang default, tetapi tanda kurung membantu menunjukkan apa yang sedang terjadi
di.
Maaf, tapi saya benar-benar tidak mengerti mengapa 5 orang memilih ini ketika tidak diakui dan tampaknya tidak bekerja pada tes sederhana: Saya mencoba ini di subdir dari /usr/share/iconsdan segera sampai di find: paths must precede expression: 22x22mana yang terakhir adalah salah satu subdirs di dalamnya . Perintah saya adalah find . -name * -print0 | grep -v "scalable" | xargs -0 -I {} cp -a {} /z/test/(memang, saya menggunakan MSYS2, jadi benar-benar masuk /mingw64/share/icons/Adwaita, tapi saya tidak bisa melihat bagaimana ini adalah kesalahan MSYS2)
underscore_d
0
EXCLUDE="foo bar blah jah"
DEST=$1
for i in*dofor x in $EXCLUDE
doif[ $x != $i ];then
cp -a $i $DEST
fidonedone
Ini salah. Beberapa masalah: Seperti yang ditulis, itu akan menyalin file yang tidak seharusnya dikecualikan beberapa kali (jumlah item yang akan dikecualikan yang dalam hal ini adalah 4). Bahkan jika Anda mencoba menyalin 'foo', item pertama dalam daftar kecualikan, itu masih akan disalin ketika Anda sampai ke x = bar dan saya masih foo. Jika Anda bersikeras melakukan ini tanpa alat yang sudah ada sebelumnya (misalnya rsync), pindahkan salinan ke pernyataan if di luar loop 'for x in ...' dan buat loop 'for x ...' ubah pernyataan logis dalam file salin if (true). Ini akan menghentikan Anda dari menyalin beberapa kali.
Eric Bringley
0
terinspirasi oleh jawaban @ SteveLazaridis, yang akan gagal, berikut adalah fungsi shell POSIX - cukup salin dan tempel ke file yang bernama cpxdi yout Anda $PATHdan buat itu executable ( chmod a+x cpr). [Sumber sekarang dikelola di GitLab saya .
#!/bin/sh# usage: cpx [-n|--dry-run] "from_path" "to_path" "newline_separated_exclude_list"# limitations: only excludes from "from_path", not it's subdirectories
cpx(){# run in subshell to avoid collisions(_CopyWithExclude"$@")}_CopyWithExclude(){case"$1"in-n|--dry-run){DryRun='echo'; shift;};;esac
from="$1"
to="$2"
exclude="$3"
$DryRun mkdir -p "$to"if[-z "$exclude"];then
cp "$from""$to"returnfi
ls -A1 "$from" \
|while IFS= read -r f;do
unset excluded
if[-n "$exclude"];thenfor x in $(printf "$exclude");doif["$f"="$x"];then
excluded=1breakfidonefi
f="${f#$from/}"if[-z "$excluded"];then
$DryRun cp -R "$f""$to"else[-n "$DryRun"]&& echo "skip '$f'"fidone}# Do not execute if being sourced["${0#*cpx}"!="$0"]&& cpx "$@"
Tampaknya tidak membantu untuk mengatakan bahwa jawaban seseorang "akan gagal" tanpa menjelaskan apa yang salah dengan itu dan bagaimana Anda memperbaikinya ...
underscore_d
@underscore_d: benar, di belakang, esp karena sekarang saya tidak bisa mengingat apa yang gagal :-(
go2null
Banyak hal: (1) menyalin file beberapa kali dan (2) logikanya masih menyalin file yang akan dikecualikan. Jalankan melalui loop menggunakan i = foo: itu akan disalin 3 kali daripada 4 untuk file lain misalnya i = test.txt.
Eric Bringley
1
terima kasih @EricBringley untuk mengklarifikasi kekurangan jawaban Steve. (Dia mengatakan itu belum diuji .)
cp -R !(dir1|dir2) path/to/destination
!(dir1|dir2)
polanyaextglob
harus dinyalakan (shopt -s extglob
untuk mengaktifkannya).Jawaban:
Gunakan rsync:
Perhatikan bahwa menggunakan
source
dansource/
berbeda. Garis miring berarti menyalin isi foldersource
ke dalamnyadestination
. Tanpa trailing slash, itu berarti menyalin foldersource
ke dalamnyadestination
.Atau, jika Anda memiliki banyak direktori (atau file) untuk dikecualikan, Anda dapat menggunakan
--exclude-from=FILE
, di manaFILE
nama file yang berisi file atau direktori untuk dikecualikan.--exclude
mungkin juga berisi wildcard, seperti--exclude=*/.svn*
sumber
rsync -av --exclude='.git/' ../old-repo/ .
Gunakan tar bersama dengan pipa.
Anda bahkan dapat menggunakan teknik ini di ssh.
sumber
Anda dapat menggunakan
find
dengan-prune
pilihan.Contoh dari
man find
:sumber
cpio
belum dikemas untuk MSYS2.Anda dapat menggunakan tar, dengan opsi --exclude, dan kemudian membukanya di tujuan. misalnya
lihat halaman manual tar untuk info lebih lanjut
sumber
Mirip dengan ide Jeff (belum diuji):
sumber
/usr/share/icons
dan segera sampai difind: paths must precede expression: 22x22
mana yang terakhir adalah salah satu subdirs di dalamnya . Perintah saya adalahfind . -name * -print0 | grep -v "scalable" | xargs -0 -I {} cp -a {} /z/test/
(memang, saya menggunakan MSYS2, jadi benar-benar masuk/mingw64/share/icons/Adwaita
, tapi saya tidak bisa melihat bagaimana ini adalah kesalahan MSYS2)Belum dicoba...
sumber
terinspirasi oleh jawaban @ SteveLazaridis, yang akan gagal, berikut adalah fungsi shell POSIX - cukup salin dan tempel ke file yang bernama
cpx
di yout Anda$PATH
dan buat itu executable (chmod a+x cpr
). [Sumber sekarang dikelola di GitLab saya .Contoh penggunaan
sumber