คัดลอกโครงสร้างโฟลเดอร์ (ไม่มีไฟล์) จากตำแหน่งหนึ่งไปยังอีกที่หนึ่ง


102

ฉันต้องการสร้างโคลนของโครงสร้างของไฟล์เซิร์ฟเวอร์หลายเทราไบต์ของเรา ฉันรู้ว่า cp --parents สามารถย้ายไฟล์และเป็นโครงสร้างหลัก แต่มีวิธีใดในการคัดลอกโครงสร้างไดเร็กทอรีเหมือนเดิมหรือไม่

ฉันต้องการคัดลอกไปยังระบบ linux และเซิร์ฟเวอร์ไฟล์ของเราติดตั้ง CIFS ไว้ที่นั่น



โซลูชัน rsync จากโพสต์ความคิดเห็นด้านบนดูดีกว่า
YE

คำตอบ:


166

คุณสามารถทำสิ่งต่างๆเช่น:

find . -type d > dirs.txt

เพื่อสร้างรายการไดเร็กทอรีจากนั้น

xargs mkdir -p < dirs.txt

เพื่อสร้างไดเรกทอรีบนปลายทาง


8
โซลูชันนี้จะใช้ไม่ได้หากคุณมีช่องว่างในชื่อไดเร็กทอรีของคุณ
Jealie

33
@Jealie เปลี่ยนคำสั่งเป็นfind . -type d -print0 >dirs.txtและxargs -0 mkdir -p <dirs.txt. สิ่งนี้จะทำให้คำสั่งทั้งสองใช้ null เป็นตัวคั่นแทนช่องว่าง
user1207177

3
xargsสามารถเกินความยาวคำสั่งสูงสุดของระบบเมื่อคุณเริ่มจัดการกับคำสั่งซื้อหลายร้อยหรือหลายพันคำดังนั้นโปรดใช้ความระมัดระวัง (ค้นหาขีดจำกัดความยาวคำสั่งด้วยgetconf ARG_MAX) ด้วยไดเร็กทอรีจำนวนมากคุณอาจต้องเขียนสคริปต์เพื่อวนรอบเอาต์พุตแทน
palswim

1
แล้วสิทธิ์และแอตทริบิวต์จะยังคงอยู่ล่ะ ??
Ashish Karpe

3
@TrevorBoydSmith: ขอบคุณสำหรับความคิดเห็นของคุณ คำถามเดิมไม่ได้กล่าวถึงสิ่งใดเกี่ยวกับความจำเป็นในการรักษาสิทธิ์การเป็นเจ้าของหรือแอตทริบิวต์ การทำเช่นนั้นจะต้องใช้วิธีแก้ปัญหาอื่นตามที่คุณกล่าวถึง แต่ข้างต้นก็เพียงพอที่จะตอบคำถามตามที่วาง
Greg Hewgill

82
cd /path/to/directories &&
find . -type d -exec mkdir -p -- /path/to/backup/{} \;

3
คำตอบที่ดีที่สุดจากฉันด้วยการค้นหา คุณสามารถลองใช้rsyncวิธีแก้ปัญหาจากคำตอบของ Chen Levy ในคำถาม SO นี้
Mat M

3
ตัวเลือกของ - mkdir คืออะไร?
Bruce_Warrior

10
--เป็นตัวยุติตัวเลือกยูทิลิตี้ GNU มาตรฐาน หมายความว่า "เฮ้ mkdir อาร์กิวเมนต์ใด ๆ หลังจากนี้ไม่ใช่แฟล็กดังนั้นให้ถือว่าเป็นอาร์กิวเมนต์ไฟล์แม้ว่าจะขึ้นต้นด้วยอักขระ" - "ก็ตาม
ยาบ้า

4
คำตอบนี้ยังไม่เก็บสิทธิ์ไดเรกทอรีและคุณลักษณะ ใช้ rynsc เพื่อรักษาสิทธิ์และคุณสมบัติ
Trevor Boyd Smith

40

นี่คือวิธีง่ายๆโดยใช้ rsync:

rsync -av -f"+ */" -f"- *" "$source" "$target"
  • หนึ่งบรรทัด
  • ไม่มีปัญหาเรื่องช่องว่าง
  • รักษาสิทธิ์

ฉันพบวิธีแก้ปัญหานี้ที่นั่น


11
เหมือนกัน แต่อ่านได้มากขึ้นrsync -a --include '*/' --exclude '*' "$source" "$target"
Sylvain

2
ปัญหาในการแก้ปัญหานี้คือ: โฟลเดอร์ของฉันมีไฟล์หลายพันไฟล์และ rsync ใช้เวลานานในการซิงค์โฟลเดอร์โหล
Christopher K.

7

ฉันไม่รู้ถ้าคุณกำลังมองหาโซลูชันบน Linux หากเป็นเช่นนั้นคุณสามารถลองสิ่งนี้:

$ mkdir destdir
$ cd sourcedir
$ find . -type d | cpio -pdvm destdir

cpio ดูเหมือนจะไม่ได้ผลสำหรับฉันอย่างน้อยก็มีพารามิเตอร์ที่คุณระบุ
r00fus

@ r00fus - โปรดอ่านคู่มือสำหรับ cpio หรืออ้างอิงgnu.org/software/cpio
zerodin

6

สิ่งนี้คัดลอกคุณสมบัติไดเร็กทอรีและไฟล์ แต่ไม่ใช่ข้อมูลไฟล์:

cp -R --attributes-only SOURCE DEST

จากนั้นคุณสามารถลบแอตทริบิวต์ของไฟล์ได้หากคุณไม่สนใจ:

find DEST -type f -exec rm {} \;

1
จะดีมาก แต่คุณลืมที่จะพูดถึงการบันทึกการเป็นเจ้าของการประทับเวลาและการอนุญาต ดังนั้นจึงสร้างความยุ่งเหยิงใน Win7 / cygwin - ผู้ใช้ NULL_SID ลำดับสิทธิ์ไม่ถูกต้องไม่สามารถแก้ไขสิทธิ์ ฯลฯ และไม่สามารถเข้าถึงโครงสร้างไฟล์ที่สร้าง
WebComer

1
ฉันควรคิดว่าโทษอยู่ที่ใครก็ตามที่พยายามใช้ Windows ในการทำงานจริง
tripleee

cp -R --attributes-only --preserve = all --parents -v SOURCE DEST
Gábor

2

วิธีแก้ปัญหาต่อไปนี้ใช้ได้ดีสำหรับฉันในสภาพแวดล้อมต่างๆ:

sourceDir="some/directory"
targetDir="any/other/directory"

find "$sourceDir" -type d | sed -e "s?$sourceDir?$targetDir?" | xargs mkdir -p

2

ใช้งานได้:

find ./<SOURCE_DIR>/ -type d | sed 's/\.\/<SOURCE_DIR>//g' | xargs -I {} mkdir -p <DEST_DIR>"/{}"

เพียงแทนที่ SOURCE_DIR และ DEST_DIR


2

สิ่งนี้ช่วยแก้ปัญหาได้แม้กระทั่งการเว้นวรรค:

ใน dir ต้นฉบับ / ต้นทาง:

find . -type d -exec echo "'{}'" \; > dirs2.txt

จากนั้นสร้างใหม่ใน dir ที่สร้างขึ้นใหม่:

mkdir -p <../<SOURCEDIR>/dirs2.txt

1

แทนที่target_dirและsource_dirด้วยค่าที่เหมาะสม:

cd target_dir && (cd source_dir; find . -type d ! -name .) | xargs -i mkdir -p "{}"

ทดสอบบน OSX + Ubuntu


0

สคริปต์ python จาก Sergiy Kolodyazhnyy โพสต์บนคัดลอกเฉพาะโฟลเดอร์ไม่ใช่ไฟล์? :

#!/usr/bin/env python
import os,sys
dirs=[ r for r,s,f in os.walk(".") if r != "."]
for i in dirs:
    os.makedirs(os.path.join(sys.argv[1],i)) 

หรือจากเปลือก:

python -c 'import os,sys;dirs=[ r for r,s,f in os.walk(".") if r != "."];[os.makedirs(os.path.join(sys.argv[1],i)) for i in dirs]' ~/new_destination

FYI:


0

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

ข้อได้เปรียบ : คุณสามารถแก้ไขหรือตรวจสอบรายการหรือถ้าคุณเขียนสคริปต์จำนวนมากและสร้างชุดของไดเร็กทอรีว่างบ่อยๆ

วิธีการ : สร้างรายการของไดเร็กทอรีโดยtreeใช้ใช้รายการนั้นเป็นอินพุตอาร์กิวเมนต์mkdir

tree -dfi --noreport > some_dir_file.txt

-dfi แสดงเฉพาะไดเร็กทอรีพิมพ์พา ธ เต็มสำหรับแต่ละชื่อทำให้ทรีไม่พิมพ์บรรทัดเยื้อง

--noreport ละเว้นการพิมพ์รายงานไฟล์และไดเร็กทอรีที่ส่วนท้ายของรายการแผนผังเพียงเพื่อให้ไฟล์เอาต์พุตไม่มีขนปุย

จากนั้นไปที่ปลายทางที่คุณต้องการไดเร็กทอรีว่างและดำเนินการ

xargs mkdir < some_dir_file.txt

0
find source/ -type f  | rsync -a --exclude-from - source/ target/

คัดลอก dir โดยได้รับอนุญาตและความเป็นเจ้าของที่เกี่ยวข้องเท่านั้น



-1

หากคุณสามารถเข้าถึงได้จากเครื่อง Windows คุณสามารถใช้ xcopy กับ / T และ / E เพื่อคัดลอกเฉพาะโครงสร้างโฟลเดอร์ (ส่วน / E มีโฟลเดอร์ว่าง)

http://ss64.com/nt/xcopy.html

[แก้ไข!]

อันนี้ใช้ rsync เพื่อสร้างโครงสร้างไดเร็กทอรีใหม่ แต่ไม่มีไฟล์ http://psung.blogspot.com/2008/05/copying-directory-trees-with-rsync.html

อาจจะดีขึ้นจริง :)


1
น่าเสียดายที่เซิร์ฟเวอร์ไฟล์ที่ให้บริการ CIFS ของเราไม่ได้ใช้งาน windows ดังนั้นจึงไม่สามารถทำคำสั่ง win
r00fus

ขอบคุณวิธี rsync ทำงานได้ดีสำหรับฉัน เข้ากันได้กับช่องว่างในชื่อไดเร็กทอรีเช่นกัน
Glutanimate

-1

นี่คือวิธีแก้ปัญหาใน php ที่:

  • คัดลอกไดเรกทอรี (ไม่เรียกซ้ำเพียงระดับเดียว)
  • รักษาสิทธิ์
  • ไม่เหมือนกับโซลูชัน rsync คือรวดเร็วแม้จะมีไดเร็กทอรีที่มีไฟล์หลายพันไฟล์เนื่องจากไม่ได้เข้าไปในโฟลเดอร์
  • ไม่มีปัญหาเรื่องช่องว่าง
  • ควรอ่านและปรับได้ง่าย

สร้างไฟล์เช่นเดียวsyncDirs.phpกับเนื้อหานี้:

<?php
foreach (new DirectoryIterator($argv[1]) as $f) {
    if($f->isDot() || !$f->isDir()) continue;
        mkdir($argv[2].'/'.$f->getFilename(), $f->getPerms());
        chown($argv[2].'/'.$f->getFilename(), $f->getOwner());
        chgrp($argv[2].'/'.$f->getFilename(), $f->getGroup());
}

เรียกใช้ในฐานะผู้ใช้ที่มีสิทธิ์เพียงพอ:

sudo php syncDirs.php /var/source /var/destination


คุณไม่จำเป็นต้องชอบ PHP และคุณไม่จำเป็นต้องใช้มัน แต่ OP ไม่ได้ระบุว่าเขาต้องการโซลูชันในภาษาใดภาษาหนึ่งหรือไม่และชอบหรือไม่ PHP ได้รับการติดตั้งบนระบบ Linux จำนวนมากเนื่องจาก 80% ของเว็บใช้ PHP ( w3techs.com/technologies/details/pl- php / ทั้งหมด / ทั้งหมด )
Christopher K.
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.