คัดลอกไฟล์ขนานจากแหล่งเดียวไปยังเป้าหมายหลาย ๆ


15

ฉันมีไฟล์ขนาดใหญ่หลายไฟล์ในสื่อออพติคัลฉันต้องการคัดลอกไปยังเป้าหมายหลาย ๆ อัน - ในกรณีนี้ฉันมีฮาร์ดไดรฟ์สองตัวติดอยู่กับคอมพิวเตอร์เครื่องเดียวกัน มียูทิลิตี้ที่สามารถใช้งานได้หรือไม่:

copy source target1 target2 ... targetN

คำตอบ:


23

สำหรับไฟล์เดียวคุณสามารถใช้teeเพื่อคัดลอกไปยังหลาย ๆ ที่:

cat <inputfile> | tee <outfile1> <outfile2> > <outfile3>

หรือหากคุณต้องการรุ่นที่ถอดถอนได้:

tee <outfile1> <outfile2> > <outfile3> < <inputfile>

โปรดทราบว่า Dennis ชี้ให้เห็นในความคิดเห็นที่teeส่งออกไปยังstdoutเช่นเดียวกับไฟล์ที่ระบุไว้ดังนั้นการใช้การเปลี่ยนเส้นทางเพื่อชี้ไปที่ไฟล์ 3 ในตัวอย่างข้างต้น นอกจากนี้คุณยังสามารถเปลี่ยนเส้นทางไปยัง/dev/nullด้านล่างนี้ - ซึ่งมีข้อดีของการทำให้รายการไฟล์สอดคล้องกันมากขึ้นในบรรทัดคำสั่ง (ซึ่งอาจทำให้ง่ายขึ้นในการเขียนสคริปต์โซลูชันสำหรับจำนวนตัวแปรของไฟล์) แต่มีประสิทธิภาพน้อยกว่าเล็กน้อย ความแตกต่างของประสิทธิภาพมีขนาดเล็ก: ใกล้เคียงกับความแตกต่างระหว่างการใช้catรุ่นหรือรุ่นที่ไม่มีcat):

cat <inputfile> | tee <outfile1> <outfile2> <outfile3> > /dev/null

คุณสามารถรวมหนึ่งในรายการข้างต้นเข้ากับfindการใช้งานหลาย ๆ ไฟล์ในไดเรกทอรีเดียวและใช้งานกับไฟล์ที่กระจายอยู่ในโครงสร้างไดเรกทอรีได้ง่ายกว่า มิฉะนั้นคุณอาจต้องตั้งค่าการคัดลอกหลายครั้งพร้อมกันเป็นงานแยกต่างหากและหวังว่าแคชของดิสก์ระบบปฏิบัติการจะสว่างและ / หรือใหญ่พอที่งานแบบขนานแต่ละงานจะใช้แคชอ่านข้อมูลจากครั้งแรกแทนที่จะเป็นสาเหตุให้หัวไดรฟ์ การนวด

ความteeพร้อมใช้งาน: มีอยู่ทั่วไปในการตั้งค่ามาตรฐานของ Linux และระบบยูนิกซ์หรือยูนิกซ์อื่น ๆ ซึ่งมักจะเป็นส่วนหนึ่งของแพ็คเกจ "coreutils" ของ GNU หากคุณกำลังใช้ Windows (คำถามของคุณไม่ได้ระบุไว้) คุณควรพบมันในพอร์ต Windows ต่าง ๆ เช่น Cygwin

ข้อมูลความคืบหน้า: เนื่องจากการคัดลอกไฟล์ขนาดใหญ่ออกจากสื่อออปติคัลอาจใช้เวลาสักครู่ (หรือผ่านเครือข่ายที่ช้าหรือไฟล์ที่มีขนาดใหญ่กว่าจากสื่อบันทึกด่วนภายในเครื่อง) ข้อมูลความคืบหน้าอาจมีประโยชน์ ในบรรทัดคำสั่งฉันมักจะใช้ไปป์วิวเวอร์ (มีให้ใน Linux distros ส่วนใหญ่ & คอลเลกชันพอร์ตของ Windows จำนวนมากและง่ายต่อการคอมไพล์ตัวเองในตำแหน่งที่ไม่สามารถใช้งานได้โดยตรง) สำหรับสิ่งนี้ - เพียงแค่แทนที่catด้วยpvดังนี้

pv <inputfile> | tee <outfile1> <outfile2> > <outfile3>

ฉันพบ tee.exe เป็นส่วนหนึ่งของแพ็คเกจ UnxUtils ขอบคุณสำหรับเคล็ดลับที่ยอดเยี่ยม!
Goyuix

5
โปรดทราบว่าteeจะส่งออกไปยัง stdout ด้วยเช่นกันดังนั้นคุณอาจต้องการทำเช่นนี้tee outputfile1 outputfile2 < inputfile > /dev/nullเนื่องจากการส่งออกไฟล์ไบนารีไปยังเทอร์มินัลอาจมีเสียงดังและยุ่งเหยิงด้วยการตั้งค่า
หยุดชั่วคราวจนกว่าจะมีการแจ้งให้ทราบต่อไป

สำหรับไดเรกทอรีและไฟล์หลาย ๆ ไฟล์ให้ใช้ tar แทน cat ตัวอย่างเช่นtar cf - file1 file2 | tee >(tar xf - -C ouput1) | tar xf - -C output2
CR

5

สำหรับ Windows:

n2ncopyจะทำสิ่งนี้:

ข้อความแสดงแทน

สำหรับ Linux:

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

OLDIFS=$IFS
IFS=$'\n'

for line in $(cat file.txt):
do
   cp file $line
done

IFS=$OLDIFS

หรือใช้ xargs:

echo dir1 dir2 dir3 | xargs -n 1 cp file1

ทั้งสองนี้จะช่วยให้คุณสามารถคัดลอกไดเรกทอรีทั้งหมด / หลายไฟล์ นอกจากนี้ยังมีการกล่าวถึงในนี้บทความ StackOverflow


ดูเหมือนว่าลิงก์ N2NCopy จะใช้งานไม่ได้
Wesley


4

อ้างอิงจากคำตอบที่ให้สำหรับคำถามที่คล้ายกันอีกวิธีหนึ่งคือใช้GNU Parallelเพื่อเรียกใช้หลายcpอินสแตนซ์ในครั้งเดียว:

parallel -j 0 -N 1 cp file1 ::: Destination1 Destination2 Destination3

คำสั่งดังกล่าวจะคัดลอก file1 ไปยังโฟลเดอร์ปลายทางทั้งสามพร้อมกัน


2

ใน bash (Linux, Mac หรือ Cygwin):

cat source | tee target1 target2 >targetN

(ทีคัดลอกข้อมูลเข้าสู่ STDOUT ดังนั้นให้ใช้การเปลี่ยนเส้นทางในเป้าหมายสุดท้าย)

ใน Windows Cygwin มักจะใช้งานมากเกินไป แต่คุณสามารถเพิ่มอดีตจากโครงการUnxUtilsซึ่งรวมถึง cat, tee และอื่น ๆ อีกมากมาย


1

วิธีแก้ปัญหาของ Ryan Thompson:

for x in dest1 dest2 dest3; do cp srcfile $x &>/dev/null &; done; wait;

ทำให้รู้สึกมาก: ถ้าความเร็วในการเขียนของปลายทาง dirs ประมาณเดียวกันแล้ว srcfile จะถูกอ่านเพียงครั้งเดียวจากดิสก์ เวลาที่เหลือจะอ่านจากแคช

ฉันจะทำให้กว้างขึ้นเล็กน้อยดังนั้นคุณก็จะได้ส่วนย่อย:

for x in dest1 dest2 dest3; do cp -a srcdir $x &; done; wait;

หากความเร็วในการเขียนของ dest dirs นั้นแตกต่างกันมาก (เช่นอันหนึ่งอยู่ใน ram disk และอีกอันบน NFS) คุณอาจเห็นว่าส่วนของ srcdir อ่านในขณะที่คัดลอก srcdir ไปยัง dest1 จะไม่อยู่ในแคชดิสก์เมื่อเขียน dest2


1

ตามคำตอบนี้: /superuser//a/1064516/702806

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

tar -c /source/dirA/ /source/file1 | tee >(cd /foo/destination3/; tar -x) >(cd /bar/destination2/; tar -x) >(cd /foobar/destination1/; tar -x) > /dev/null

หากต้องการใช้งานในสคริปต์คุณอาจต้องเปิดใช้สคริปต์ด้วย bash -x script.sh


ตลก. ฉันคิดว่า "มันสมเหตุสมผลแล้วมี upvote" upvoted จากนั้นฉันตรวจสอบลิงก์ ... : D
Kamil Maciorowski

นี่เป็นคำตอบที่ชัดเจนกว่าคำตอบ (ยอมรับ) ของ David Spillettหากคุณกำลังคัดลอกไฟล์หลายไฟล์พร้อมกัน สำหรับไฟล์ต้นฉบับไฟล์เดียวข้อดีที่ฉันเห็นได้tarคือมันจะทำการคัดลอก (เก็บรักษา) คุณสมบัติของไฟล์โดยอัตโนมัติ (เช่นวันที่แก้ไข / เวลาโหมด (ป้องกัน) และ ACLs ที่อาจเกิดขึ้นเจ้าของ / กลุ่ม (ถ้ามีสิทธิ์), SELinux บริบท (ถ้ามี), คุณลักษณะเพิ่มเติม (ถ้ามี), ฯลฯ ) ………………… PS ผู้ใช้จะต้องใช้bash -xทำไม?
สกอตต์

ฉันใช้#!/bin/shที่จุดเริ่มต้นของสคริปต์ แต่ไม่ยอมรับไวยากรณ์ของคำสั่ง คุณสามารถใช้bash -xหรือ#!/bin/bashที่จุดเริ่มต้นของไฟล์ของคุณ ฉันไม่รู้ว่าทำไมถึงมีความแตกต่างระหว่างshและbashการตีความ
Rémi Girard

Kamil Maciorowski - ฉันไม่รู้ว่าทำไมคำตอบของคุณถึงไม่ถูกโหวต มันเป็นทางออกที่สมบูรณ์แบบ ฉันต้องการแบ่งปัน
Rémi Girard

0

ในทุบตี:

for x in dest1 dest2 dest3; do cp srcfile $x &>/dev/null &; done; wait;

2
ฉันไม่คิดว่ามันจะทำงานได้ดี ในสำเนาคู่ขนานที่สมบูรณ์แบบที่คุณต้องอ่านหนึ่งครั้งเขียนหลาย ๆ ครั้ง ฉันคิดว่าสิ่งนี้จะทำ 1: 1 อ่าน: เขียน บางทีถ้าสำเนาเริ่มเร็วพอและแคชไดรฟ์มีขนาดใหญ่พอคุณไม่จำเป็นต้องหาหัวอ่าน
ต้มตุ๋น Quixote

0

ถ้าคุณต้องการที่จะทำเช่นนี้ใน Windows PowerShell จากมันเป็นไปไม่ได้โดยปริยายเพราะแตกต่างจาก-Pathข้อโต้แย้งที่-Destinationไม่ได้ใช้เวลาหลายข้อโต้แย้ง อย่างไรก็ตามคุณสามารถใช้-Passthroughและ daisy-chain คำสั่ง (แต่ก็ไม่สนุก)

ทางออกที่ดีที่สุดคือการทำด้วยตัวเองเป็นที่แสดงให้เห็นที่นี่

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