cp ทำงานอย่างประหลาดเมื่อ (dot) หรือ .. (dot dot) เป็นไดเรกทอรีต้นทาง


15

คำตอบนี้แสดงให้เห็นว่าสามารถคัดลอกไฟล์ทั้งหมด - รวมถึงไฟล์ที่ซ่อน - จากไดเรกทอรีsrcไปยังไดเรกทอรีdestเช่น:

mkdir dest
cp -r src/. dest

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

ฉันลองทำบางสิ่ง ครั้งแรกกรณีปกติ:

$ mkdir src src/src_dir dest && touch src/src_file src/.dotfile dest/dest_file
$ cp -r src dest
$ ls -A dest
dest_file  src

จากนั้น/.ในตอนท้าย:

$ mkdir src src/src_dir dest && touch src/src_file src/.dotfile dest/dest_file
$ cp -r src/. dest
$ ls -A dest
dest_file  .dotfile  src_dir  src_file

ดังนั้นสิ่งนี้จะทำงานคล้าย*กัน แต่ยังคัดลอกไฟล์ที่ซ่อนอยู่

$ mkdir src src/src_dir dest && touch src/src_file src/.dotfile dest/dest_file
$ cp -r src/* dest
$ ls -A dest
dest_file  src_dir  src_file

.และ..ฮาร์ดลิงก์ที่เหมาะสมดังอธิบายไว้ที่นี่เช่นเดียวกับรายการไดเรกทอรีเอง

พฤติกรรมนี้มาจากที่ใดและมีการจัดทำเอกสารไว้ที่ใด


3
คุณหมายถึงไม่มีใครสามารถค้นหาเอกสารได้ cpอ้างอิงอย่างชัดเจนอธิบายวิธีการcp -Rทำงาน .และ..เป็นไดเรกทอรีเช่นเดียวกับไดเรกทอรีอื่น ๆ ไม่มีอะไรวิเศษหรือลึกลับเกี่ยวกับพวกเขา
AlexP

2
@AlexP ฉันแก้ไขคำตอบเพื่อให้ชัดเจนยิ่งขึ้น ประเด็นทั้งหมดคือ.และ..ไม่ทำตัวเหมือนไดเรกทอรีอื่น ๆ
iFreilicht

ฉันพยายามอธิบายว่าทำไมมันถึงทำงานได้ที่วิธีคัดลอกโฟลเดอร์แบบวนซ้ำโดยใช้ cp
35911

คำตอบ:


27

cp -Rพฤติกรรมที่เป็นผลเชิงตรรกะของอัลกอริทึมสำหรับเอกสาร ดูPOSIXขั้นตอนที่ 2f:

ไฟล์ในไดเรกทอรีsource_fileจะถูกคัดลอกไปยังไดเรกทอรีdest_fileการสี่ขั้นตอน (1-4) อยู่ที่นี่กับไฟล์เป็นsource_files

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

src/.เป็นไดเรกทอรีปัจจุบันภายในsrcซึ่งเป็นของsrcตัวเอง; src/src_dir/..คือsrc_dirsrcของไดเรกทอรีแม่ซึ่งเป็นอีกครั้งที่ ดังนั้นจากภายนอกsrcหากsrcเป็นไดเรกทอรีการระบุsrc/.หรือsrc/src_dir/..เป็นไฟล์ต้นฉบับcpนั้นเทียบเท่าและคัดลอกเนื้อหาของsrcรวมถึงไฟล์ที่ซ่อนอยู่

จุดของการระบุsrc/.ก็คือว่ามันจะล้มเหลวหากsrcไม่ใช่ไดเรกทอรี (หรือลิงก์สัญลักษณ์ไปยังไดเรกทอรี) แต่ทว่าsrcจะไม่เกิดขึ้น มันจะคัดลอกเนื้อหาของsrcเท่านั้นโดยไม่ต้องคัดลอกsrcตัวเอง นี่ตรงกับเอกสารด้วย:

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

ดังนั้นcp -R src/. destคัดลอกเนื้อหาของsrcไปยังdest/.(ไฟล์ต้นฉบับคือ.ในsrc) ในขณะที่cp -R src destคัดลอกเนื้อหาของsrcการdest/srcใช้งาน (ไฟล์ที่มาsrc)

วิธีการที่จะคิดว่านี้ก็คือการเปรียบเทียบการคัดลอกsrc/src_dirและsrc/.มากกว่าการเปรียบเทียบและsrc/. มีพฤติกรรมเหมือนในอดีตsrc.src_dir


แต่มันก็ไม่ได้ทำตัวเหมือนกัน ระบุsrcจะคัดลอกลงในไดเรกทอรีdest, src/.จะคัดลอกเนื้อหา ฉันจะพยายามทำให้คำถามนั้นชัดเจนยิ่งขึ้น
iFreilicht

ฉันคิดว่านั่นเป็นคำตอบสำหรับคำถามพื้นฐานของคุณ
Stephen Kitt

1
@ Stéphane OP เปรียบเทียบการคัดลอกsrc/.และsrc/*(หมายเหตุไม่ใช่ src/.* ); src/*ไม่รวมไฟล์ที่ซ่อนอยู่หาก globbing ละเว้นไฟล์เหล่านั้น ...
Stephen Kitt

1
อืม "ไดเรกทอรีที่มีsource_file " อย่างชัดเจนsrcประกอบด้วยsrc/.แต่ก็หมายความว่าไดเรกทอรีที่มีของไดเรกทอรีขึ้นอยู่กับวิธีที่คุณตั้งชื่อไดเรกทอรี แน่นอนว่าการมี.ลิงก์ในทางหมายความว่าไดเรกทอรีทั้งหมดมีตัวเอง แต่อาจไม่ง่ายสำหรับทุกคน แทนที่จะมีพฤติกรรมนี้เราอาจถูกล่อลวงให้คิดว่า "ไดเรกทอรีที่มีไดเรกทอรีfoo" จะถูกกำหนดโดยfoo/..ในกรณีนี้มันจะไม่สำคัญว่าเราจะอ้างถึงfooหรือfoo/.: ไดเรกทอรีที่มีผลลัพธ์จะเหมือนกัน
ilkkachu

1
ซึ่งก็คือการบอกว่าความแตกต่างระหว่างfooและfoo/.ดูเหมือนจะละเอียดอ่อน แต่ฉันไม่รังเกียจฉันยังพบว่ามันสนุกเล็กน้อย
ilkkachu

1

เมื่อคุณเรียกคุณจะได้รับcp -R src/foo dest dest/fooดังนั้นถ้าไดเรกทอรีdest/fooไม่อยู่cpจะสร้างมันขึ้นมาและจากนั้นคัดลอกเนื้อหาของการsrc/foodest/foo

เมื่อคุณเรียกใช้cp -R src/. dest, cpเห็นว่าdest/.มีอยู่แล้วก็แค่เรื่องของการคัดลอกเนื้อหาของการsrc/.dest/.

เมื่อคุณคิดว่าเป็นการคัดลอกไดเรกทอรีชื่อ.จากsrcและรวมเนื้อหากับไดเรกทอรีที่มีอยู่dest/.มันจะทำให้รู้สึก

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