ฉันมีไฟล์ขนาดใหญ่หลายไฟล์ในสื่อออพติคัลฉันต้องการคัดลอกไปยังเป้าหมายหลาย ๆ อัน - ในกรณีนี้ฉันมีฮาร์ดไดรฟ์สองตัวติดอยู่กับคอมพิวเตอร์เครื่องเดียวกัน มียูทิลิตี้ที่สามารถใช้งานได้หรือไม่:
copy source target1 target2 ... targetN
ฉันมีไฟล์ขนาดใหญ่หลายไฟล์ในสื่อออพติคัลฉันต้องการคัดลอกไปยังเป้าหมายหลาย ๆ อัน - ในกรณีนี้ฉันมีฮาร์ดไดรฟ์สองตัวติดอยู่กับคอมพิวเตอร์เครื่องเดียวกัน มียูทิลิตี้ที่สามารถใช้งานได้หรือไม่:
copy source target1 target2 ... targetN
คำตอบ:
สำหรับไฟล์เดียวคุณสามารถใช้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
จะส่งออกไปยัง stdout ด้วยเช่นกันดังนั้นคุณอาจต้องการทำเช่นนี้tee outputfile1 outputfile2 < inputfile > /dev/null
เนื่องจากการส่งออกไฟล์ไบนารีไปยังเทอร์มินัลอาจมีเสียงดังและยุ่งเหยิงด้วยการตั้งค่า
tar cf - file1 file2 | tee >(tar xf - -C ouput1) | tar xf - -C output2
สำหรับ 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
อ้างอิงจากคำตอบที่ให้สำหรับคำถามที่คล้ายกันอีกวิธีหนึ่งคือใช้GNU Parallelเพื่อเรียกใช้หลายcp
อินสแตนซ์ในครั้งเดียว:
parallel -j 0 -N 1 cp file1 ::: Destination1 Destination2 Destination3
คำสั่งดังกล่าวจะคัดลอก file1 ไปยังโฟลเดอร์ปลายทางทั้งสามพร้อมกัน
ใน bash (Linux, Mac หรือ Cygwin):
cat source | tee target1 target2 >targetN
(ทีคัดลอกข้อมูลเข้าสู่ STDOUT ดังนั้นให้ใช้การเปลี่ยนเส้นทางในเป้าหมายสุดท้าย)
ใน Windows Cygwin มักจะใช้งานมากเกินไป แต่คุณสามารถเพิ่มอดีตจากโครงการUnxUtilsซึ่งรวมถึง cat, tee และอื่น ๆ อีกมากมาย
วิธีแก้ปัญหาของ 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
ตามคำตอบนี้: /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
tar
คือมันจะทำการคัดลอก (เก็บรักษา) คุณสมบัติของไฟล์โดยอัตโนมัติ (เช่นวันที่แก้ไข / เวลาโหมด (ป้องกัน) และ ACLs ที่อาจเกิดขึ้นเจ้าของ / กลุ่ม (ถ้ามีสิทธิ์), SELinux บริบท (ถ้ามี), คุณลักษณะเพิ่มเติม (ถ้ามี), ฯลฯ ) ………………… PS ผู้ใช้จะต้องใช้bash -x
ทำไม?
#!/bin/sh
ที่จุดเริ่มต้นของสคริปต์ แต่ไม่ยอมรับไวยากรณ์ของคำสั่ง คุณสามารถใช้bash -x
หรือ#!/bin/bash
ที่จุดเริ่มต้นของไฟล์ของคุณ ฉันไม่รู้ว่าทำไมถึงมีความแตกต่างระหว่างsh
และbash
การตีความ
ในทุบตี:
for x in dest1 dest2 dest3; do cp srcfile $x &>/dev/null &; done; wait;
ถ้าคุณต้องการที่จะทำเช่นนี้ใน Windows PowerShell จากมันเป็นไปไม่ได้โดยปริยายเพราะแตกต่างจาก-Path
ข้อโต้แย้งที่-Destination
ไม่ได้ใช้เวลาหลายข้อโต้แย้ง อย่างไรก็ตามคุณสามารถใช้-Passthrough
และ daisy-chain คำสั่ง (แต่ก็ไม่สนุก)