เป็นไปได้หรือไม่ที่จะคัดลอกไฟล์เดียวไปยังหลายไดเรกทอรีโดยใช้คำสั่ง cp?
ฉันลองสิ่งต่อไปนี้ซึ่งใช้งานไม่ได้:
cp file1 /foo/ /bar/
cp file1 {/foo/,/bar}
ฉันรู้ว่ามันเป็นไปได้โดยใช้ for loop หรือ find แต่มันเป็นไปได้โดยใช้คำสั่ง gnu cp?
เป็นไปได้หรือไม่ที่จะคัดลอกไฟล์เดียวไปยังหลายไดเรกทอรีโดยใช้คำสั่ง cp?
ฉันลองสิ่งต่อไปนี้ซึ่งใช้งานไม่ได้:
cp file1 /foo/ /bar/
cp file1 {/foo/,/bar}
ฉันรู้ว่ามันเป็นไปได้โดยใช้ for loop หรือ find แต่มันเป็นไปได้โดยใช้คำสั่ง gnu cp?
คำตอบ:
ไม่cp
สามารถคัดลอกหลายแหล่งได้ แต่จะคัดลอกไปยังปลายทางเดียวเท่านั้น คุณต้องจัดให้มีการเรียกใช้cp
หลายครั้ง - หนึ่งครั้งต่อปลายทาง - สำหรับสิ่งที่คุณต้องการทำ ใช้อย่างที่คุณบอกว่าเป็นลูปหรือเครื่องมืออื่น ๆ
คุณไม่สามารถทำสิ่งนี้ได้ด้วยตัวcp
เอง แต่คุณสามารถรวมcp
กับxargs
:
echo dir1 dir2 dir3 | xargs -n 1 cp file1
จะคัดลอกfile1
ไปdir1
, และ dir2
จะโทรถึง3 ครั้งเพื่อดูรายละเอียดdir3
xargs
cp
xargs
cp
เพียงอย่างเดียว" เพราะคำตอบที่พยายามจะเป็นประโยชน์โดยการแนะนำวิธีอื่นไม่ได้หมายความว่าไม่ได้ตอบคำถาม
echo dir[1-3] | xargs -n 1 cp filename
)
สัญลักษณ์แทนยังทำงานกับรหัส Roberts
echo ./fs*/* | xargs -n 1 cp test
เท่าที่ฉันเห็นคุณสามารถใช้สิ่งต่อไปนี้:
ls | xargs -n 1 cp -i file.dat
-i
ตัวเลือกในการหมายถึงคำสั่งที่คุณจะถูกถามว่าจะเขียนทับแฟ้มในไดเรกทอรีปัจจุบันด้วยcp
file.dat
แม้ว่ามันจะไม่ใช่ทางออกอัตโนมัติอย่างสมบูรณ์ แต่ก็ใช้ได้ผลสำหรับฉัน
-i
ป้องกันไว้คุณจะไม่ถามคุณเกี่ยวกับการเขียนทุกไฟล์ใช่ไหม แทนที่จะคัดลอกไปยังไดเรกทอรีหรือไม่
cp: overwrite
คำถามหลายข้อ แต่ฉันไม่ต้องตอบคำถามใด ๆ และไม่ได้เขียนทับไฟล์
ผมจะใช้cat
และtee
ขึ้นอยู่กับคำตอบที่ผมเห็นที่/superuser/32630/parallel-file-copy-from-single-source-to-multiple-targetscp
แทน
ตัวอย่างเช่น:
cat inputfile | tee outfile1 outfile2 > /dev/null
cat <inputfile> | tee /path-to-files/outfile{1..4} > /dev/null
tee < inputfile outfile1 outfile2 > /dev/null
เป็นรูปแบบที่มีประโยชน์ตามคำตอบของ Taywee สังเกตการใช้การเปลี่ยนเส้นทาง io ด้วย '<' เพื่อไม่จำเป็นต้องใช้ piping จาก cat
คำตอบเหล่านี้ดูเหมือนจะซับซ้อนกว่าชัดเจน:
for i in /foo /bar; do cp "$file1" "$i"; done
for d in */ ; do cp $file "$i" done
ls -db di*/subdir | xargs -n 1 cp File
-b
ในกรณีที่มีช่องว่างในชื่อไดเรกทอรีมิฉะนั้นมันจะแตกเป็นรายการอื่นโดย xargs มีปัญหากับรุ่น echo นี้
ไม่ได้ใช้ cp ต่อ se แต่ ...
สิ่งนี้เกิดขึ้นกับฉันในบริบทของการคัดลอกวิดีโอ Gopro จำนวนมากออกจากการ์ด SD (ช้า) ไปยังไดรฟ์ USB สาม (ช้า) ฉันต้องการอ่านข้อมูลเพียงครั้งเดียวเพราะใช้เวลาตลอดไป และฉันต้องการมันซ้ำ
$ tar cf - src | tee >( cd dest1 ; tar xf - ) >( cd dest2 ; tar xf - ) | ( cd dest3 ; tar xf - )
(และคุณสามารถเพิ่มได้มากขึ้นในส่วน> () ส่วนหากคุณต้องการผลลัพธ์เพิ่มเติม)
ฉันไม่ได้ทำการเปรียบเทียบ แต่มันเร็วกว่า cp-in-a-loop (หรือการเรียกใช้ cp แบบขนาน)
หากต้องการใช้การคัดลอกxargs
ไปยังไดเรกทอรีที่ใช้ไวด์การ์ดบน Mac OS โซลูชันเดียวที่ทำงานกับฉันด้วยช่องว่างในชื่อไดเรกทอรีคือ:
find ./fs*/* -type d -print0 | xargs -0 -n 1 cp test
ที่ไหนtest
คือแฟ้มที่จะคัดลอก
และ./fs*/*
ไดเรกทอรีที่จะคัดลอกไป
ปัญหาคือว่า xargs เห็นช่องว่างเป็นอาร์กิวเมนต์ใหม่วิธีการเปลี่ยนอักขระตัวคั่นที่ใช้-d
หรือ-E
น่าเสียดายที่ทำงานบน Mac OS ไม่ถูกต้อง
หากคุณต้องการทำโดยไม่มีคำสั่ง forked:
tee <inputfile file2 file3 file4 ... >/dev/null
เป็นหลักเทียบเท่ากับคำตอบ xargs แต่ในกรณีที่คุณต้องการประมวลผลแบบขนาน:
parallel -q cp file1 ::: /foo/ /bar/
ตัวอย่างเช่นหากต้องการคัดลอก file1 ลงในไดเรกทอรีย่อยทั้งหมดของโฟลเดอร์ปัจจุบัน (รวมถึงการเรียกซ้ำ):
parallel -q cp file1 ::: `find -mindepth 1 -type d`
หมายเหตุ: นี่อาจเป็นเพียงการบ่งบอกถึงการเพิ่มขึ้นของความเร็วที่เห็นได้ชัดเจนสำหรับกรณีการใช้งานที่เฉพาะเจาะจงเช่นหากแต่ละไดเรกทอรีเป้าหมายเป็นดิสก์ที่แตกต่างกัน
นอกจากนี้ยังเป็นหน้าที่คล้ายกับอาร์กิวเมนต์ '-P' สำหรับ xargs
ไม่คุณไม่สามารถ.
ฉันพบหลายครั้งที่ฉันสามารถใช้ฟังก์ชั่นนี้ดังนั้นฉันจึงได้ทำเครื่องมือของตัวเองเพื่อทำสิ่งนี้ให้ฉัน
http://github.com/ddavison/branch
ค่อนข้างง่าย -
branch myfile dir1 dir2 dir3
/e
เพียงแค่ครั้งเดียวในแต่ละเครื่องฉันก็สามารถเขียนเครื่องมือไฟฟ้าของตัวเองและเก็บมันไว้ตลอดไป
สมมติว่าคุณต้องการคัดลอกfileName.txt
ไปยังไดเรกทอรีย่อยทั้งหมดภายในไดเรกทอรีทำงานปัจจุบัน
รับชื่อไดเรกทอรีย่อยทั้งหมดls
และบันทึกเป็นไฟล์ชั่วคราวบางคำพูดallFolders.txt
ls > allFolders.txt
xargs
พิมพ์รายชื่อและผ่านมันไปที่คำสั่ง
cat allFolders.txt | xargs -n 1 cp fileName.txt
อีกวิธีหนึ่งคือใช้ cat และ tee ดังนี้:
cat <source file> | tee <destination file 1> | tee <destination file 2> [...] > <last destination file>
ฉันคิดว่ามันจะไม่มีประสิทธิภาพเลยทีเดียวเนื่องจากงานจะถูกแบ่งออกเป็นหลาย ๆ กระบวนการ (หนึ่งต่อปลายทาง) และฮาร์ดไดรฟ์จะเขียนไฟล์หลายไฟล์พร้อมกันในส่วนต่าง ๆ ของแผ่นเสียง อย่างไรก็ตามหากคุณต้องการเขียนไฟล์ไปยังไดรฟ์ที่แตกต่างกันหลายวิธีนี้อาจมีประสิทธิภาพพอสมควร
ใช้สคริปต์ทุบตี
DESTINATIONPATH[0]="xxx/yyy"
DESTINATIONPATH[1]="aaa/bbb"
..
DESTINATIONPATH[5]="MainLine/USER"
NumberOfDestinations=6
for (( i=0; i<NumberOfDestinations; i++))
do
cp SourcePath/fileName.ext ${DESTINATIONPATH[$i]}
done
exit
หากคุณต้องการคัดลอกหลาย ๆ โฟลเดอร์ไปยังหลาย ๆ โฟลเดอร์คุณสามารถทำสิ่งนี้ได้:
echo dir1 dir2 dir3 | xargs -n 1 cp -r / path / toyourdir / {subdir1, subdir2, subdir3}
หากไดเรกทอรีเป้าหมายทั้งหมดของคุณตรงกับนิพจน์พา ธ - เหมือนกับไดเรกทอรีย่อยทั้งหมดpath/to
- เพียงใช้find
ร่วมกับcp
สิ่งนี้:
find ./path/to/* -type d -exec cp [file name] {} \;
แค่นั้นแหละ.
find
ในเธรด
หากคุณจำเป็นต้องระบุว่าโฟลเดอร์ใดที่จะคัดลอกไฟล์คุณสามารถรวมการค้นหากับ greps อย่างน้อยหนึ่งรายการ ตัวอย่างเช่นการแทนที่ favicon.ico ในโฟลเดอร์ย่อยใด ๆ ที่คุณสามารถใช้:
find . | grep favicon\.ico | xargs -n 1 cp -f /root/favicon.ico
สิ่งนี้จะคัดลอกไปยังไดเรกทอรีย่อยทันทีหากคุณต้องการเจาะลึกกว่านี้ให้ปรับ-maxdepth
พารามิเตอร์
find . -mindepth 1 -maxdepth 1 -type d| xargs -n 1 cp -i index.html
หากคุณไม่ต้องการคัดลอกไปยังไดเรกทอรีทั้งหมดหวังว่าคุณสามารถกรองไดเรกทอรีที่คุณไม่สนใจตัวอย่างการคัดลอกไปยังโฟลเดอร์ทั้งหมดที่ขึ้นต้นด้วย a
find . -mindepth 1 -maxdepth 1 -type d| grep \/a |xargs -n 1 cp -i index.html
หากการคัดลอกไปยังชุดไดเรกทอรีโดยพลการ / แยกจากกันคุณจะต้องมีคำแนะนำของ Robert Gamble
ฉันต้องการคัดลอกไฟล์ไปยังหลายไดเรกทอรีเช่น:
cp file1 /foo/; cp file1 /bar/; cp file1 /foo2/; cp file1 /bar2/
และคัดลอกไดเรกทอรีไปยังไดเรกทอรีอื่น:
cp -r dir1/ /foo/; cp -r dir1/ /bar/; cp -r dir1/ /foo2/; cp -r dir1/ /bar2/
ฉันรู้ว่ามันเหมือนการออกคำสั่งหลายอย่าง แต่มันทำงานได้ดีสำหรับฉันเมื่อฉันต้องการพิมพ์ 1 บรรทัดและเดินออกไปซักพัก
ตัวอย่างเช่นถ้าคุณอยู่ในไดเรกทอรีหลักของโฟลเดอร์ปลายทางที่คุณสามารถทำได้:
สำหรับฉันใน $ (ls); ทำ cp sourcefile $ i; เสร็จแล้ว
ls
และอ้างถึงตัวแปรเสมอ for i in ./*; do cp sourcefile "$i"; done