การคัดลอกไฟล์ที่ซ่อนอยู่ซ้ำ ๆ - Linux


19

มีวิธีง่ายๆในการคัดลอกไฟล์ที่ซ่อนอยู่ทั้งหมดซ้ำในไดเรกทอรีไปยังไดเรกทอรีอื่นหรือไม่? ฉันต้องการสำรองข้อมูลไฟล์การตั้งค่าทั้งหมดในโฮมไดเร็คทอรี่ไม่ใช่ไฟล์ปกติ ฉันเหนื่อย:

cp -R .* directory

แต่จะจดจำ.และ..คัดลอกไฟล์ที่ไม่ได้ซ่อนไว้ทั้งหมดซ้ำด้วยซ้ำ มีวิธีรับ cp เพื่อละเว้น.และ..?


มีความแตกต่างระหว่าง-rและ-R?
Chaminda Bandara

คำตอบ:


15

ฉันชอบย้าย dirs โดยทั่วไปแล้ว:

tar cvf - . | (cd /dest/dir; tar xvf -)

ซึ่งจะแยกค่าไดเรกทอรีปัจจุบันไปยัง stdout จากนั้นไปป์ที่ subshell ที่ cd แรกของไปยังไดเรกทอรีปลายทางก่อนทำการยกเลิกการ stdin ง่าย ๆ โดยตรงและสามารถขยายได้ - พิจารณาสิ่งที่เกิดขึ้นเมื่อคุณแทนที่ () ด้วย ssh ไปยังเครื่องอื่น หรือเพื่อตอบคำถามของคุณคุณอาจทำ:

tar cvf - .* --exclude=\. --exclude=\.\. | (cd /dest/dir; tar xvf -)

1
ขอบคุณตัวเลือกไม่รวมคือสิ่งที่ฉันต้องการ ฉันได้ทำไปแล้วอย่างอื่น แต่ฉันจะเก็บไว้ใช้อ้างอิงในอนาคต ดูเหมือนว่าจะมีความยืดหยุ่นจริงๆ (แม้ว่าอาจช้ากว่า)
Zifre

1
คำปรึกษาที่ดี. ฉันมีสองการปรับปรุง: 1) cd /dest/dir && tar xvf -การใช้งาน &&จะหยุดคุณจากการ blatting กว่าไดเรกทอรีต้นทางถ้าคุณมีการพิมพ์ผิดในปลายทาง 2) คุณจำเป็นต้องใช้การvตั้งค่าสถานะtar บนคำสั่ง tar อย่างใดอย่างหนึ่ง
Tom Shaw

ยุติธรรมพอสมควร ฉันยังได้รับทราบเพื่อสิ่งที่กลุ่มวิธีการอื่น ๆ : การคัดลอก srcdir ระยะไกลไปยังที่นี่ทำ(cd /src/dir && tar cf - .) | tar xvf -
pjz

17

เกือบทุกครั้งที่สิ่งนี้สามารถแก้ไขได้ด้วย:

cp -R .[a-zA-Z0-9]* directory

มันค่อนข้างแปลกที่จะมีไฟล์ที่ซ่อนอยู่ซึ่งไม่ได้ขึ้นต้นด้วยตัวละครตัวหนึ่ง

การจับคู่รูปแบบอื่น ๆ พร้อมใช้งาน ( .??*, .[^.]*) - ดูความคิดเห็น


สิ่งนั้นจะไม่สนใจ.-xyz - ข้อมูลใน [] ตรงกับอักขระตัวแรกหลังจากจุด
Hamish Downer

6
. [^.] * จะจับทุกอย่าง
falstro

1
... ยกเว้นสิ่งที่เริ่มต้นด้วยสองช่วงเวลา
falstro

@roe - ที่รุ่นดีเกินไป
Alnitak

@mish - ใช่ฉันพูดมากในคำตอบ
Alnitak

11

rsyncคุณสามารถใช้

rsync -a ./ /some/other/directory/

ที่จะคัดลอกเนื้อหาของไดเรกทอรีปัจจุบัน (รวมถึงไฟล์ dot แต่ไม่รวม..)


ง่ายและใช้งานได้กับไฟล์ที่ซ่อนอยู่ในโฟลเดอร์ที่ซ่อนอยู่ด้วย
user59183

สำหรับฉันนี่เป็นความสับสนน้อยลงและมีประสิทธิภาพมากที่สุดของการแก้ปัญหาที่ให้ไว้
palerdot

ทางออกที่ดี ฉันต้องการมันด้วยเพื่อไม่ให้คัดลอกข้าม.gitdirs เพิ่ม -C ไม่นี้และเพื่อให้คำสั่งกลายเป็น:rsync -aC ./ /some/other/directory/
theruss

10

ฉันขอร้องคุณออกห่างจากการขยายเชลล์ธรรมดาในcpบรรทัดคำสั่ง - การขยายเชลล์มีทุกมุมของahem "สนใจ" มุมกรณี (recursion ที่ไม่พึงประสงค์ที่เกิดจาก. และ .. , ช่องว่าง, สิ่งที่ไม่พิมพ์, hardlinks, ลิงก์สัญลักษณ์และ เป็นต้น) ใช้findแทน (มันมาในfindutilsแพ็คเกจ, ในกรณีที่คุณไม่ได้ติดตั้ง - ซึ่งจะแปลก, การกระจายทั้งหมดติดตั้งโดยค่าเริ่มต้น):

find -H /path/to/toplevel/dir/ -maxdepth 1 -name '.*' -a \( -type d -o -type f -o -type l \) -exec cp -a '{}' /path/to/destination/dir/ \;

คำอธิบายทีละขั้นตอน:

  • -Hจะทำให้findไม่ติดตาม symlinks (ยกเว้นว่าชื่อไดเรกทอรีระดับบนสุดที่คุณให้ไว้คือ symlink ซึ่งจะเป็นไปตาม)
  • /path/to/toplevel/dir/ เห็นได้ชัดว่าควรจะถูกแทนที่โดยคุณด้วยเส้นทางทำไดเรกทอรีที่โฮสต์ไฟล์การตั้งค่าและไดเรกทอรีที่คุณต้องการสำรอง
  • -maxdepth 1จะหยุดไม่ให้findซ้ำลงไปในไดเรกทอรีใด ๆ ที่มีชื่อขึ้นต้นด้วยจุด เราไม่ต้องการให้เงินคืนcpเราจะทำเช่นนั้นสำหรับเราเราแค่ต้องการชื่อในระดับนี้
  • -name '.*'บอกfindว่าเราต้องการชื่อทั้งหมดที่ขึ้นต้นด้วยจุด สิ่งนี้จะไม่ทำงานอย่างถูกต้องหากPOSIXLY_CORRECTตั้งค่าตัวแปรสภาพแวดล้อมแต่ไม่ค่อยมี (ถ้าเคย) นี่เป็นเงื่อนไขการจับคู่ครั้งแรกที่เราได้ระบุไว้
  • a \( ....... \)เป็นและตามด้วยเงื่อนไขที่ซับซ้อนมากขึ้นในวงเล็บ (ฉันใช้ ..... เพื่อแทนที่มันได้อธิบายไว้ด้านล่าง) เราจำเป็นต้องหลบเลี่ยงวงเล็บเนื่องจากมิฉะนั้นพวกเขาจะตีความผิด (เชลล์) โดยเชลล์ ดังนั้นแบ็กสแลชที่อยู่ข้างหน้า
  • -type d -o -type f -o -type lเป็นสามเงื่อนไขด้วยหรือระหว่างพวกเขา -type dจับคู่ไดเรกทอรี-type fจับคู่ไฟล์ปกติและ-type lจับคู่สัญลักษณ์ คุณสามารถเลือกสิ่งที่คุณต้องการ - ตัวอย่างเช่นหากคุณไม่ต้องการสำรองข้อมูลไดเรกทอรีการตั้งค่าให้ข้าม-type d(และ-oด้านหลังขวา)
  • -exec ..... \;บอกfindให้รันคำสั่งทุกครั้งที่พบการแข่งขัน จุดสิ้นสุดของคำสั่งถูกทำเครื่องหมายด้วยเครื่องหมายอัฒภาคซึ่งเราต้องหลบกลับด้วยแบ็กสแลชอีกครั้งเพื่อหลีกเลี่ยงการตีความเชลล์ ภายในบรรทัดคำสั่งนั้นคุณต้องใช้{}ตำแหน่งที่คุณต้องการให้ชื่อของการแข่งขันที่พบในปัจจุบันสิ้นสุดลง ตั้งแต่เปลือกหอยอาจตีความผิดวงเล็บปีกกาคุณควรวางไว้ใน apostrophes '{}'ในขณะที่ คำสั่งที่เราต้องการดำเนินการในกรณีนี้คือcp -a '{}' /path/to/destination/dir/(-a หมายถึงไฟล์เก็บถาวรซึ่งเกิดขึ้นซ้ำในไดเรกทอรีย่อยคัดลอก symlink เป็นลิงก์และรักษาสิทธิ์และแอตทริบิวต์เพิ่มเติมและ/path/to/destination/dir/เห็นได้ชัดว่าเป็นชื่อของไดเรกทอรีปลายทาง - แทนที่มัน)

ดังนั้นในภาษาอังกฤษธรรมดาfindบรรทัดคำสั่งนี้บอกว่า:

เริ่มต้นที่ / path / to / toplevel / dir / อย่าลงไปในไดเรกทอรีย่อยใด ๆ ค้นหาไดเรกทอรีไฟล์และ symlink ทั้งหมดที่ชื่อขึ้นต้นด้วยจุด สำหรับแต่ละสิ่งที่คุณพบพบให้คัดลอกไปยัง / path / to / destination / dir / รักษาธรรมชาติสิทธิ์และแอตทริบิวต์เพิ่มเติม


1
find เป็นสิ่งที่มีประโยชน์ที่สุดเท่าที่เคยมีมา
นายเงางามและใหม่安宇

1
คำตอบที่ดี แม้ว่าฉันต้องการ -exec ... ';' หลีกเลี่ยงการทับขวาหมายถึงคำสั่งนี้จะทำงานทั้งในและ CLI ใน crontab :))
kubanczyk

8

ฉันใช้เสมอ? * เพื่อค้นหาไฟล์ที่ซ่อนอยู่โดยไม่ได้รับ "." และ ".. " มันอาจจะพลาด ".a" หรือบางสิ่งบางอย่าง แต่ฉันไม่เคยมีหนึ่งในนั้น


แน่นอนดีและเรียบร้อย :) +1
falstro

ฉันไม่ต้องการให้มันล้มเหลวอย่างลึกลับหากมี ".a" บางอย่าง
Zifre

ฉันชอบเพราะถ้าคุณรู้ว่าคุณไม่มีไฟล์ที่ซ่อนตัวอักษรเดียวมันพิมพ์เร็วมาก
Paul Tomblin

นี่จะเป็นคำตอบที่ดีที่สุด มันควรจะถูกเลื่อนขึ้นไปด้านบน
Ibn Saeed

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