วิธีการให้คำสั่ง 'cp' ไม่เกิดข้อผิดพลาดเมื่อไม่มีไฟล์ต้นฉบับอยู่


59

ฉันใช้ Mac OS X ฉันพยายามคัดลอกไฟล์บางไฟล์ด้วยคำสั่ง cp เพื่อสร้างสคริปต์เช่นนี้

cp ./src/*/*.h ./aaa

แต่คำสั่งนี้ทำให้เกิดข้อผิดพลาดหากไม่มีไฟล์. h ในไดเร็กทอรี. / src วิธีทำให้คำสั่งไม่เริ่มข้อผิดพลาด? (ความล้มเหลวเงียบ) ข้อผิดพลาดทำให้ผลการสร้างล้มเหลว แต่ฉันต้องการคัดลอกเมื่อมีไฟล์ส่วนหัวบางส่วนเท่านั้น

คำตอบ:


69

หากคุณกำลังพูดถึงข้อความแสดงข้อผิดพลาดคุณสามารถระงับได้โดยส่งไปยังที่เก็บข้อมูลบิต:

cp ./src/*/*.h ./aaa 2>/dev/null

หากคุณต้องการระงับรหัสออกและข้อความแสดงข้อผิดพลาด:

cp ./src/*/*.h ./aaa 2>/dev/null || :

8
มันเป็นการดีที่จะอธิบายความ:หมายในบริบทนี้
Piotr Dobrogost

23
@PiotrDobrogost: ใน Bash และเชลล์อื่น ๆ โคลอนคือยูทิลิตี null (no-op) มันระบุไว้โดยPOSIX เนื่องจากมันส่งกลับค่าจริงเสมอจึงใช้ที่นี่เพื่อระงับรหัสทางออกของล้มเหลวcp(ควรเป็นที่ต้องการ) builtin shell trueสามารถใช้แทนและอ่านได้ง่ายขึ้น
Dennis Williamson


1
สิ่งนี้จะไม่สนใจข้อผิดพลาดอื่น ๆ (ไม่มีไดเรกทอรีต้นทาง / ปลายทางไฟล์ต้นฉบับอยู่ แต่ไม่สามารถอ่านได้ดิสก์เต็มระบบไฟล์แบบอ่านอย่างเดียวข้อผิดพลาด IO cpไม่อยู่ในPATHอย่างใด ... )
Vladimir Panteleev

ข้อผิดพลาดทางไวยากรณ์ใกล้โทเค็นที่ไม่คาดคิด `|| '
ทัง

13

คุณกำลังมองหาบางอย่างตามสายของ

if [ -e file ]
 then cp file /somewhere
fi

(น่าเสียดายที่-fตัวเลือกไม่ใช่ Droid ที่คุณต้องการ)

หากคุณต้องการจับคู่แบบกลมนั้นจะไม่ทำงาน ใช้findแทนเช่น:

find ./src -name \*.h -exec cp {} ./destination \;

โปรดทราบว่าอาจมีปัญหา TOCTOU ที่อาจเกิดขึ้นกับวิธีการดังกล่าว (เช่นหากคุณใช้set -eและไฟล์จะหายไประหว่าง[และการcpเรียกสคริปต์ของคุณจะผิดพลาด)
Vladimir Panteleev

9

คำถามเก่า แต่อาจยังเกี่ยวข้องกับผู้อื่น
หากคุณไม่ต้องการใช้ cp คุณสามารถลอง rsync ได้
หากต้องการคัดลอกไฟล์ทั้งหมดจากแหล่งข้อมูลไปยังไดเรกทอรีปลายทางให้รัน:

rsync -avzh --ignore-errors /path/to/source /path/to/destination

Rsync มาพร้อมกับระบบ Unix เช่น Linux, Mac OS X หรือ FreeBSD


4
คุณสามารถใช้ rsync แทน cp โดยเพิ่มพารามิเตอร์--ignore-missing-args: rsync -av --ignore-missing-args ./src/*/*.h ./aaaนี่เป็นข้อได้เปรียบเหนือกว่า--ignore-errorsข้อผิดพลาดที่ถูกละเว้นเท่านั้นคือสิ่งที่เกี่ยวข้องกับไฟล์ต้นฉบับที่ไม่มีอยู่ ด้วย--ignore-errorsข้อผิดพลาดทุกคนจะไม่สนใจซึ่งอาจจะเป็นอันตราย นอกจากนี้ให้คำนึงถึงว่าพารามิเตอร์นี้ค่อนข้างล่าสุดดังนั้นจึงอาจไม่มีใน rsync เวอร์ชันเก่า
jesjimher

6

การวางผลลัพธ์ให้เป็นจริงจะทำให้มั่นใจว่าคำสั่งจะประสบความสำเร็จเสมอ ฉันได้ลองใน Linux แต่ไม่ได้อยู่ใน Mac OS ใด ๆ :

cp ./src/*/*.h ./aaa | true

5
ไปป์อย่างง่าย|จะทำงานในขณะที่||ทำในกรณีที่มีข้อผิดพลาดเท่านั้น และtrueมักเป็นเลขฐานสองในขณะที่เครื่องหมายจุดคู่:เป็นแบบบิลท์และไม่กิน PID
ott--

สคริปต์ทุบตีบน MacOS - Yosemite ที่มีคำสั่ง "cp ./src/*/*.h ./aaa" ไม่ผิดพลาดหากไฟล์. h ไม่มีอยู่
Vivek

2

คุณสามารถบังคับสถานะข้อผิดพลาดที่ถูกต้อง ด้วยฟังก์ชั่น:

$ cpalways () { cp $1 $2 2>/dev/null ; return 0 ; }

รับดังต่อไปนี้:

$ ls foo bar baz
ls: baz: No such file or directory
bar foo

การทำสำเนาปกติจะส่งคืนข้อผิดพลาด มันจะกลับสถานะการออกจาก 1

$ cp baz bar ; echo $?
cp: baz: No such file or directory
1

หากเราใช้ฟังก์ชัน cpalways () ด้านบนข้อผิดพลาดจะถูกซ่อน:

$ cpalways baz bar ; echo $?
0
$ cpalways foo bar ; echo $?
0
$ cpalways baz bar ; echo $?
0
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.