มูลค่าเพิ่มของตัวเลือก -T ใน GNU cp และ mv คืออะไร?


26

ทำไมคำสั่ง GNU Coreutils ถึงมี-T/--no-target-directoryตัวเลือก? ดูเหมือนว่าทุกอย่างที่ทำได้สามารถทำได้โดยใช้ซีแมนทิกส์ของ.(จุดตัวเอง) ในลำดับชั้นไดเรกทอรี Unix แบบดั้งเดิม

พิจารณา:

cp -rT /this/source dir

-Tตัวเลือกที่จะช่วยป้องกันการคัดลอกจากการสร้างdir/sourceไดเรกทอรีย่อย ค่อนข้าง/this/sourceจะถูกระบุด้วยdirและเนื้อหาจะถูกแมประหว่างต้นไม้ตามลำดับ ดังนั้นสำหรับตัวอย่างเช่น/this/source/foo.cไปdir/foo.cและอื่น ๆ dir/source/foo.cมากกว่าที่จะ

แต่สามารถทำได้อย่างง่ายดายโดยไม่ต้อง-Tใช้ตัวเลือก:

cp -r /this/source/. dir  # Probably worked fine since dawn of Unix?

ความหมายองค์ประกอบจุดต่อท้ายจะถูกคัดลอกเป็นเด็กของdirแต่แน่นอนว่า "เด็ก" ที่มีอยู่แล้ว (เพื่อไม่ต้องถูกสร้างขึ้น) และเป็นจริงdirตัวเองเพื่อให้ผลเป็นที่ยึดติดกับ/this/pathdir

มันทำงานได้ดีถ้าไดเรกทอรีปัจจุบันเป็นเป้าหมาย:

cp -r /this/tree/node/. . # node's children go to current dir

มีบางสิ่งที่คุณสามารถทำได้ด้วยสิ่งเดียว-Tที่ทำให้การดำรงอยู่ของมันมีเหตุผล? (นอกจากการรองรับระบบปฏิบัติการที่ไม่ได้ใช้งานไดเรกทอรีดอทแล้วเหตุผลที่ไม่ได้กล่าวถึงในเอกสาร)

เคล็ดลับจุดด้านบนไม่สามารถแก้ไขสภาพการแข่งขันเดียวกันกับที่กล่าวไว้ในเอกสาร GNU Info ได้-Tหรือไม่?

คำตอบ:


29

.เคล็ดลับของคุณสามารถใช้ได้เฉพาะเมื่อคุณคัดลอกไดเรกทอรีไม่ใช่ไฟล์ -Tตัวเลือกที่ทำงานร่วมกับทั้งไดเรกทอรีและไฟล์ ถ้าคุณทำ:

cp srcfile destfile

และมีไดเรกทอรีชื่อdestfileมันจะคัดลอกไปdestfile/srcfileซึ่งอาจไม่ได้ตั้งใจ ดังนั้นคุณใช้

cp -T srcfile destfile

และคุณได้รับข้อผิดพลาดอย่างถูกต้อง:

cp: cannot overwrite directory `destfile' with non-directory

หากคุณลองใช้.วิธีการสำเนาจะไม่ทำงาน:

cp: cannot stat `srcfile/.`: Not a directory

.เคล็ดลับไม่ทำงานเมื่อคัดลอกไฟล์เพียงแค่ไม่ได้เมื่อเปลี่ยนชื่อ basename ในเวลาเดียวกัน! cp /path/to/file /target/dir/. หาก/target/dir/fileมีอยู่และเป็นไดเรกทอรีคุณจะได้รับการวินิจฉัยเหมือนกัน! แต่คุณได้แสดงให้เห็นแล้วว่าสิ่ง-Tใดที่ไม่สามารถทำได้หากไม่มีมันในขั้นตอนเดียวโดยไม่มีเงื่อนไขการแข่งขัน: คัดลอกไฟล์และเปลี่ยนชื่อโดยไม่ถูกแบ่งเป็นไดเรกทอรีย่อย
Kaz

3
นั่นคือไม่เหมือนกัน - มี.เคล็ดลับที่คุณกำลังพูดคุยเกี่ยวกับการผนวก/.กับแหล่งที่มา
Barmar

21

ปัญหาเกี่ยวกับcp/ mv/ lnตามที่พวกเขาได้รับการออกแบบมาตั้งแต่แรกนั้นคือพวกเขามีสองคำสั่งในหนึ่งเดียว ( คัดลอกและคัดลอกลง )

cp A B

เป็นการคัดลอก A ไป Bหรือคัดลอก A ไป B ( คัดลอก A ไป B / A ) ขึ้นอยู่กับว่าBมีอยู่จริงหรือไม่และเป็นไดเรกทอรีหรือไม่ (และรูปแบบอื่น ๆ ถ้า B เป็น symlink ไปยังไดเรกทอรี)

ไม่ดีเพราะมันคลุมเครือ ดังนั้นการนำ GNU ไปใช้จึงได้เพิ่มตัวเลือกในการแก้ไข

cp -T A B

คัดลอก A ไป Bโดยไม่คำนึงถึง หากBมีอยู่และเป็นไดเรกทอรีนั่นจะล้มเหลว (เว้นแต่คุณจะผ่าน-r) ไม่ว่าในกรณีใด ๆ คุณจะไม่สิ้นสุดAไฟล์ภายในBเมื่อคุณต้องการAคัดลอกไปยัง B

และ:

cp -t B A

เป็นสำเนาลงใน


ปรัชญา unix ดั้งเดิมคือการสมมติว่าคุณรู้ว่าคุณทำอะไรและจะช่วยให้คุณยิงตัวเองอย่างมีความสุข
Lenne

4
@Lenne แต่ที่นี่ไม่ได้ช่วยให้คุณหลีกเลี่ยงการยิงตัวเองด้วยการเดินเท้า หากมีคนสร้างไดเรกทอรี B หรือ symlink ไปยังบางไดเรกทอรีก่อนที่คุณจะเรียกใช้cp A Bคำสั่งจะไม่ทำสิ่งที่คุณตั้งใจ และการทำ[ -e B ] || [ -L B ] || cp A Bยังคงมีสภาพการแข่งขันที่cp -Tn A Bไม่มี
Stéphane Chazelas

6

-Tสามารถให้ความล้มเหลวถ้าไดเรกทอรีที่ไม่ถูกต้องที่มีอยู่สำหรับสิ่งที่ควรจะไฟล์หัวข้อ:

$ mkdir mustbeafile
$ touch afile
$ cp -T afile mustbeafile
cp: cannot overwrite directory `mustbeafile' with non-directory
$ echo $?
1
$ cp afile mustbeafile
$ 

นั่นคือแทนที่จะประสบความสำเร็จโดยไม่คาดคิดคัดลอกไปยัง subdir คำเตือนและสถานะการออกที่ไม่ดีเกิดขึ้นซึ่งอาจทำให้สคริปต์หยุดทำงานและมนุษย์ตรวจสอบว่าเหตุใดจึงมีไดเรกทอรีที่ไม่ควรมี เป็นหนึ่ง


0

การใช้แฟล็กนั้นมีความชัดเจนมากขึ้นและมีความเสี่ยงน้อยลงจากเอฟเฟกต์ที่ไม่ตั้งใจเมื่อใช้คำสั่งในสคริปต์แทนการป้อนด้วยตนเอง การปะจุดลงบนพา ธ ในสคริปต์อาจจบลงด้วยความเสียหายที่ไม่คาดคิดทุกชนิด

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