วิธีคัดลอกไฟล์บางไฟล์ แต่ไม่ใช่ทั้งหมด?


54

ดังนั้นคุณสามารถใช้*เป็นบัตรเสริมสำหรับไฟล์ทั้งหมดเมื่อใช้cpภายในบริบทของไดเรกทอรี มีวิธีการคัดลอกไฟล์ทั้งหมดยกเว้นxไฟล์หรือไม่

คำตอบ:


42

ในbashคุณสามารถใช้extglob:

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

โดย!(b*)ไม่รวมb*ไฟล์ทั้งหมด

คุณสามารถปิดการใช้งานในภายหลังextglobด้วย

 $ shopt -u extglob

คุณรู้หรือไม่ว่ามีบางสิ่งที่เทียบเท่ากับเชลล์ tcsh
Levon

น่าเสียดายที่ฉันทำไม่ได้ ดูเหมือนว่าfindเป็นวิธีเดียวในtcsh:find . -maxdepth 1 ! -name "exclude*" -exec cp -t destination {} \+
เร่ง

50

Rsync จัดการอย่างนี้

ตัวอย่างคัดลอกทั้งหมด: rsync -aP /folder1/* /folder/2

ตัวอย่างการคัดลอกทั้งหมดยกเว้น: rsync -aP --exclude=x /folder1/* /folder2/

-aPสวิทช์:

a: คล้ายกับcp -aเวียนเกิดซ้ำเป็นต้น P: แสดงความคืบหน้าคุณสมบัติที่ดีของ rsync


5
และดูคำตอบนี้สำหรับคำแนะนำสั้น ๆ เกี่ยวกับรายการยกเว้นทั่วไปของ rsync
Gilles 'หยุดความชั่วร้าย'

1
บน darwin / MacOS ให้ใช้-rPแทน-aPถ้าคุณต้องการเรียกคืน -aสำหรับการเก็บถาวร ไม่แน่ใจว่าสิ่งนี้มีการเปลี่ยนแปลงหรือไม่หรือแตกต่างจาก MacOS
jpoveda

rsyncไม่มีตัวเลือกเพื่อให้สามารถเรียกซ้ำได้ ตัวอย่าง: rsync --recursive -P --exclude=x /folder1/* /folder2/. (ผ่านการทดสอบบน Ubuntu เท่านั้น)
n1k31t4

12

นี่ไม่ใช่คุณสมบัติของcpมันเป็นคุณสมบัติของเชลล์ของคุณ (ขยาย*เพื่อหมายถึงไฟล์ที่ไม่ใช่จุดทั้งหมด) ดังนั้นคำตอบขึ้นอยู่กับเชลล์ที่คุณใช้ ตัวอย่างเช่นzshรองรับไวยากรณ์นี้:

$ cp ^x /path/to/destination

ที่ไหน^x"ไฟล์ทั้งหมดยกเว้นx" ในกรณีที่

คุณสามารถรวมรูปแบบการเลือกและการยกเลิกการเลือกเช่นเพื่อคัดลอกไฟล์ wav ทั้งหมดยกเว้นที่มี xyz คุณสามารถใช้:

cp *.wav~*xyz*

ความคิดเห็นใด ๆ เกี่ยวกับbash?
ชาดแฮร์ริสัน

@ hydroparadise ฉันไม่รู้อะไรเกี่ยวกับ bash มากนัก แต่คำตอบนี้ดูเหมือนจะครอบคลุม
Michael Mrozek

แล้ว tcsh ล่ะ ใครรู้บ้าง
Levon

4

นอกจากนี้ยังสามารถทำได้ในเปลือก bourne แบบเก่า (แบบพกพา / ใช้งานร่วมกันได้) ในหลากหลายวิธีด้วยเครื่องมือมาตรฐานในรูปแบบที่หรูหราน้อยกว่าการใช้เชลล์แบบกลมหรือคำสั่งเชลล์ขั้นสูงที่มีตัวเลือกในการยกเว้น

หากมีไฟล์ไม่มากเกินไป (และไม่มีชื่อรวมถึงช่องว่างและ / หรือ linebreaks) อาจเป็นวิธี:

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

แน่นอนbashและเครื่องมือของ GNU นั้นยอดเยี่ยมและทรงพลัง แต่ก็ยังไม่พร้อมเสมอ หากคุณตั้งใจจะใส่ไว้ในสคริปต์พกพาฉันอยากจะแนะนำfindในความคิดเห็นโดย Rush


2
ฉันพบว่าส่วนสุดท้ายของคำตอบของคุณแค่เบี่ยงเบนความสนใจจากหัวข้อที่อยู่ในมือ นอกจากนี้ "Unix" ไม่ใช่มาตรฐานทองคำอีกต่อไป (ถ้าเคยเป็น) มันไม่เกี่ยวข้องเลยถ้ามีบางอย่าง "Unix" หรือไม่อีกต่อไปแม้ว่าชื่อของไซต์นี้จะเป็น "Unix และ Linux"
Alexander

2
ตกลง. ฉันย้ายความคิดเห็นไปที่นี่แทน: Unix ไม่ใช่ GNU ฉันยอมรับว่า "ความไม่สม่ำเสมอ" ของสิ่งต่าง ๆ ไม่น่าสนใจมากนัก แต่ฉันก็ยังเชื่อในการพกพาและการรู้ประวัติของคุณสักหน่อย
MattBianco

เห็นด้วยอย่างเต็มที่กับคุณที่นั่น
Alexander

2

หากคุณต้องการคัดลอกทุกสิ่งในโฟลเดอร์ (รวมถึงโฟลเดอร์ย่อย) ไปยังไดเรกทอรีย่อยเฉพาะ:

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

ใช้งานได้กับ sh, bash, zsh (อย่างน้อย)


1
โน้มน้าวฉันว่านี่ไม่ใช่เจตนาเดียวกันcp -R * subdir/
roaima

1
หากคุณใช้คำสั่ง "cp -R * subdir /" bash / zsh พยายามที่จะคัดลอก 'subdir' ซ้ำ ๆ คุณพบข้อผิดพลาด: "ชื่อยาวเกินไป (ไม่คัดลอก)"
user2707671

จุดดี. คำแนะนำของคุณพยายามหลีกเลี่ยงคำเตือนจากcp(ไม่ใช่จากbash/ sh), " cp: cannot copy a directory, ‘subdir’, into itself, ‘subdir/subdir’" แม้ว่าการทำสำเนาจะเสร็จสมบูรณ์อย่างถูกต้อง โชคไม่ดีที่ตัวแปรของคุณหยุดพักด้วยชื่อไฟล์ใด ๆ ที่มีช่องว่างหรือเครื่องหมายวรรคตอนที่อ่อนไหวต่อเชลล์ ดูunix.stackexchange.com/q/128985/135943
roaima

-1

extglob เป็นวิธีที่ดีที่สุดที่ฉันคาดเดา

อีกวิธีคือการใช้ cp $(ls --ignore=x) subdir/


สิ่งนี้จะทำให้ได้รับอักขระพิเศษทุกรูปแบบในชื่อไฟล์ (พื้นที่, บรรทัดใหม่$ฯลฯ ) lsไม่เคยแยกการส่งออกของ unix.stackexchange.com/q/128985/135943
Wildcard
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.