ฉันต้องการคัดลอกไฟล์ทั้งหมดในไดเรกทอรียกเว้นบางไฟล์ในไดเรกทอรีย่อยที่ระบุ ฉันสังเกตเห็นว่าคำสั่ง 'cp' ไม่มีตัวเลือก - ยกเว้น ดังนั้นฉันจะบรรลุสิ่งนี้ได้อย่างไร
tar -c | tar -x
?
ฉันต้องการคัดลอกไฟล์ทั้งหมดในไดเรกทอรียกเว้นบางไฟล์ในไดเรกทอรีย่อยที่ระบุ ฉันสังเกตเห็นว่าคำสั่ง 'cp' ไม่มีตัวเลือก - ยกเว้น ดังนั้นฉันจะบรรลุสิ่งนี้ได้อย่างไร
tar -c | tar -x
?
คำตอบ:
rsync นั้นง่ายและรวดเร็ว:
rsync -av --progress sourcefolder /destinationfolder --exclude thefoldertoexclude
คุณสามารถใช้--exclude
หลายครั้ง
rsync -av --progress sourcefolder /destinationfolder --exclude thefoldertoexclude --exclude anotherfoldertoexclude
โปรดทราบว่าแบบ dir thefoldertoexclude
หลังจากที่--exclude
ตัวเลือกที่เป็นญาติไปคือsourcefolder
sourcefolder/thefoldertoexclude
นอกจากนี้คุณสามารถเพิ่ม-n
สำหรับการรันแบบแห้งเพื่อดูสิ่งที่จะถูกคัดลอกก่อนที่จะดำเนินการจริงและถ้าทุกอย่างเรียบร้อยให้ลบออก-n
จากบรรทัดคำสั่ง
--exclude
thefoldertoexclude
ญาติกับsourcefolder
หรือ dir ทำงานปัจจุบัน? ขอบคุณ
rsync -av --progress --exclude="thefoldertoexclude" sourcefolder /destinationfolder
- อยู่ดี upvote สำหรับ rsync แทนการค้นหาที่เป็นคุณสามารถใช้เส้นทางที่แน่นอนสำหรับแหล่งที่มาในขณะที่พบว่ามันเป็น trickier ในขณะที่มันใช้{}
ใน dst
$ rsync user@example.com:/var/www/mypage /var/www/mylocalpage/
หรือจากโลคอลไปยังรีโมต$ rsync /var/www/mylocalpage/ user@example.com:/var/www/mypage
ถ้าการยกเว้นรูปแบบชื่อไฟล์บางอย่างนั้นต้องถูกดำเนินการโดยยูทิลิตี้ไฟล์ยูนิกซ์ - อิชทุกไฟล์ (เช่น cp, mv, rm, tar, rsync, scp, ... ) การทำสำเนาของความพยายามครั้งยิ่งใหญ่จะเกิดขึ้น แต่สิ่งเหล่านี้สามารถทำได้โดยเป็นส่วนหนึ่งของการโค้งงอเช่นโดยเปลือก
man 1 bash
, extglob/
ตัวอย่าง:
$ shopt -s extglob $ echo images / * images / 004.bmp images / 033.jpg images / 1276338351183.jpg images / 2252.png $ echo images /! (*. jpg) images / 004.bmp images / 2252.png
ดังนั้นคุณเพียงแค่ใส่รูปแบบภายใน!()
และมันตรงข้ามกับการแข่งขัน รูปแบบอาจมีความซับซ้อนตามอำเภอใจเริ่มจากการแจงนับเส้นทางแต่ละเส้นทาง (ตามที่ Vanwaril แสดงในคำตอบอื่น): !(filename1|path2|etc3)
ไปยังสิ่งที่คล้าย regex กับดาวและคลาสอักขระ อ้างถึง manpage สำหรับรายละเอียด
man 1 zshexpn
, รุ่นชื่อไฟล์/
คุณสามารถทำได้setopt KSH_GLOB
และใช้รูปแบบเหมือนทุบตี หรือ,
% setopt EXTENDED_GLOB % echo images / * images / 004.bmp images / 033.jpg images / 1276338351183.jpg images / 2252.png % echo images / * ~ * .jpg images / 004.bmp images / 2252.png
ดังนั้นx~y
ตรงกับรูปแบบรูปแบบx
แต่ไม่รวม y
อีกครั้งสำหรับรายละเอียดเต็มดู manpage
ปลาเปลือกมีคำตอบสวยมากนี้:
🐟 cp (การจับคู่สตริง -v '* .excluded.names' - srcdir / *) destdir
พิมพ์cp *
Hit CtrlX*แล้วดูว่าเกิดอะไรขึ้น มันไม่เป็นอันตรายฉันสัญญา
zsh
แต่
setopt -u extglob
การปิดคุณลักษณะการจับคู่รูปแบบในการขยายทุบตีวิ่ง
ทำไมต้องใช้rsync
เมื่อคุณสามารถทำได้:
find . -type f -not -iname '*/not-from-here/*' -exec cp '{}' '/dest/{}' ';'
สิ่งนี้จะถือว่าโครงสร้างไดเรกทอรีเป้าหมายเหมือนกันกับแหล่งที่มา
-path
อาร์กิวเมนต์เพื่อทดสอบลำดับชั้นของเส้นทางไม่ใช่ -iname
find . -type f -not -path '*/not-from-here/*' -exec cp '{}' '/dest/{}' \;
rsync
? เพราะมันอาจจะไม่ปรากฏในระบบ! ในขณะที่find
, cp
เสมอในสถานที่ของพวกเขา หรือคุณจากคนที่ติดตั้ง 2gigs ของสิ่งที่ทำสิ่งที่ง่าย
cp -r `ls -A | grep -v "c"` $HOME/
# $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 }
วิธีที่ง่ายที่สุดที่ฉันพบซึ่งคุณสามารถคัดลอกไฟล์ทั้งหมดยกเว้นไฟล์และโฟลเดอร์เพียงแค่เพิ่มชื่อไว้ในวงเล็บ:
shopt -s extglob
cp -r !(Filename1 | FoldernameX | Filename2) Dest/
-bash: !: event not found
ขยายความคิดเห็นของ mvdsมันใช้งานได้สำหรับฉัน
cd dotfiles
tar -c --exclude .git --exclude README . | tar -x -C ~/dotfiles2
มันสัมพันธ์กับไดเรกทอรีต้นทาง
นี่จะเป็นการยกเว้นไดเรกทอรีที่source/.git
จะคัดลอก
rsync -r --exclude '.git' source target
rsync
rsync -r --verbose --exclude 'exclude_pattern' ./* /to/where/
และก่อนอื่นให้ลองด้วยตัวเลือก -n เพื่อดูว่าจะคัดลอกอะไร
ฉันคิดว่าคุณกำลังใช้ bash หรือ dash จะใช้งานได้ไหม
shopt -s extglob # sets extended pattern matching options in the bash shell
cp $(ls -laR !(subdir/file1|file2|subdir2/file3)) destination
การทำ ls ไม่รวมไฟล์ที่คุณไม่ต้องการและใช้มันเป็นอาร์กิวเมนต์แรกสำหรับ cp
ls
cp !(file1|file1) dest
cp $(ls folder/!exclude_folder0|exclude_folder1)) dest
อีกตัวเลือกที่ง่ายกว่าคือการติดตั้งและใช้ rsync ซึ่งมีตัวเลือก --exclude-dir และสามารถใช้สำหรับไฟล์ทั้งในตัวเครื่องและจากระยะไกล
rsync
จริงๆแล้วค่อนข้างยุ่งยาก ต้องทำหลาย ๆ การทดสอบเพื่อให้มันใช้งานได้
สมมติว่าคุณต้องการคัดลอก/var/www/html
ไป/var/www/dev
แต่จำเป็นที่จะต้องยกเว้น /var/www/html/site/video/
ไดเรกทอรีอาจเนื่องจากขนาดของมัน คำสั่งจะเป็น:
rsync -av --exclude 'sites/video' /var/www/html/ /var/www/dev
ข้อแม้บางอย่าง:
/
จำเป็นต้องใช้สแลชสุดท้ายในแหล่งข้อมูลมิฉะนั้นจะคัดลอกไดเรกทอรีต้นทางแทนที่จะเป็นเนื้อหาและกลายเป็น/var/www/dev/html/xxxx
ซึ่งอาจไม่ใช่สิ่งที่คุณต้องการที่--exclude
เส้นทางเป็นญาติกับแหล่งที่มาโดยตรง แม้ว่าคุณจะใส่เส้นทางที่สมบูรณ์ แต่ก็จะไม่ทำงาน
-v
สำหรับ verbose -a
สำหรับโหมดเก็บถาวรซึ่งหมายความว่าคุณต้องการเรียกซ้ำและต้องการรักษาเกือบทุกอย่าง
cp -rv `ls -A | grep -vE "dirToExclude|targetDir"` targetDir
แก้ไข: ลืมที่จะยกเว้นเส้นทางเป้าหมายเช่นกัน (ไม่เช่นนั้นจะเป็นการคัดลอกซ้ำ)
นี่คือการแก้ไขคำตอบของ Linus Kleen คำตอบของเขาไม่ทำงานสำหรับฉันเพราะจะมี เพิ่มไว้ด้านหน้าของพา ธ ไฟล์ที่ cp ไม่ชอบ (พา ธ จะดูเหมือน source / .destination / file)
คำสั่งนี้ใช้ได้สำหรับฉัน:
find . -type f -not -path '*/exlude-path/*' -exec cp --parents '{}' '/destination/' \;
คำสั่ง --parents เก็บรักษาโครงสร้างไดเร็กทอรี
เพียงแค่ย้ายมันชั่วคราวไปยังไดเรกทอรีที่ซ่อนอยู่ (และเปลี่ยนชื่อหลังจากถ้าต้องการ)
mkdir .hiddendir
cp * .hiddendir -R
mv .hiddendir realdirname
cp
และมาตรฐาน POSIX sh
เปลือกเช่น
mv tobecopied/tobeexcluded .
cp -r tobecopied dest/
mv tobeexcluded tobecopied/
ฉันใช้การวนรอบ "ทำในขณะที่" เพื่ออ่านผลลัพธ์ของคำสั่ง find ในตัวอย่างนี้ฉันกำลังจับคู่ (แทนที่จะยกเว้น) รูปแบบบางอย่างเนื่องจากมีจำนวนรูปแบบที่ จำกัด ที่ฉันต้องการมากกว่าที่ฉันไม่ต้องการ คุณสามารถย้อนกลับตรรกะด้วย -not ที่ด้านหน้าของแฟล็ก -iname:
find . -type f -iname "*.flac" -o -print0 -iname "*.mp3" -print0 -o -iname "*.wav" -print0 -o -iname "*.aac" -print0 -o -iname "*.wma" -print0 | while read -d $'\0' file; do cp -ruv "$file" "/media/wd/network_sync/music/$file"; done
ฉันใช้ข้างต้นเพื่อคัดลอกไฟล์ประเภทเพลงทั้งหมดที่ใหม่กว่าบนเซิร์ฟเวอร์ของฉันมากกว่าไฟล์ใน Western Digital TV Live Hub ที่ฉันติดตั้งที่ / media / wd ฉันใช้ข้างต้นเพราะฉันมีไฟล์ DVD, mpegs และอื่น ๆ จำนวนมากที่ฉันต้องการยกเว้นและเพราะเหตุผลบางประการ rsync ดูเหมือนว่ามันเป็นการคัดลอก แต่หลังจากที่ฉันดูอุปกรณ์ wd ไฟล์จะไม่อยู่ที่นั่นแม้จะไม่มี ข้อผิดพลาดระหว่าง rsync ด้วยคำสั่งนี้:
rsync -av --progress --exclude=*.VOB --exclude=*.avi --exclude=*.mkv --exclude=*.ts --exclude=*.mpg --exclude=*.iso --exclude=*ar --exclude=*.vob --exclude=*.BUP --exclude=*.cdi --exclude=*.ISO --exclude=*.shn --exclude=*.MPG --exclude=*.AVI --exclude=*.DAT --exclude=*.img --exclude=*.nrg --exclude=*.cdr --exclude=*.bin --exclude=*.MOV --exclude=*.goutputs* --exclude=*.flv --exclude=*.mov --exclude=*.m2ts --exclude=*.cdg --exclude=*.IFO --exclude=*.asf --exclude=*.ite /media/2TB\ Data/data/music/* /media/wd/network_sync/music/
ls -I "filename1" -I "filename2" | xargs cp -rf -t destdir
ส่วนแรกls
ไฟล์ทั้งหมด -I
แต่เฉพาะไฟล์ที่ซ่อนอยู่กับธง เอาต์พุตของls
ใช้เป็นอินพุตมาตรฐานสำหรับส่วนที่สอง xargs
สร้างและดำเนินการคำสั่งcp -rf -t destdir
จากอินพุตมาตรฐาน ธง-r
หมายถึงการคัดลอกไดเรกทอรีซ้ำ-f
หมายถึงการคัดลอกไฟล์บังคับซึ่งจะเขียนทับไฟล์ในdestdir
, -t
ระบุสำเนาไดเรกทอรีปลายทาง
cp -r ls -A | grep -v "Excluded_File_or_folder"
../$target_location -v