ฉันจะคัดลอกหลายไฟล์ด้วยไวด์การ์ดได้อย่างไร


42

ฉันมีโฟลเดอร์ที่มีไฟล์จำนวนหนึ่งอยู่ในนั้น ABC. * (มีไฟล์ประมาณ 100 ไฟล์) ฉันต้องการคัดลอกไฟล์ทั้งหมดไปยังไฟล์ใหม่ด้วยชื่อที่ขึ้นต้นด้วย DEF *

ดังนั้นฉันต้องการ

ABC.Page1
ABC.Page2
ABC.Topic12
...etc

คัดลอกไปยัง

DEF.Page1
DEF.Page2
DEF.Topic12
...etc

วิธีที่ง่ายที่สุดในการทำเช่นนี้กับคำสั่งแบทช์ (ใน BASH หรือคล้ายกัน) คืออะไร? ฉันกำลังคิดอะไรบางอย่างที่เกี่ยวข้องกับ sed หรือ awk หรือ xargs แต่ฉันมีปัญหาในการหาไวยากรณ์ ฉันสามารถเขียนสคริปต์ Python ได้ แต่ฉันคิดว่าอาจมีโซลูชันบรรทัดคำสั่งที่ไม่ซับซ้อนเกินไป


ตัวmcจัดการไฟล์ที่น่าเคารพมีการสนับสนุนที่ครอบคลุมมากที่สุดสำหรับการเปลี่ยนชื่อจำนวนมาก
oakad

@oakad tarไม่ใช่ไก่ฤดูใบไม้ผลิเช่นกัน ดูคำตอบของฉันสำหรับตัวอย่าง
mikeserv

คำตอบ:


41

สิ่งที่เกี่ยวกับสิ่งนี้ในทุบตี:

for file in ABC.*; do cp "$file" "${file/ABC/DEF}";done

คุณสามารถทดสอบได้โดยใส่ echo ไว้ด้านหน้าคำสั่ง cp:

for file in ABC.*; do echo cp "$file" "${file/ABC/DEF}";done

สมบูรณ์ ง่ายกว่าที่ฉันจินตนาการไว้
Octopus

มันจะดีพอในกรณีส่วนใหญ่ แต่การตรวจสอบด้วยเสียงก้องเป็นสิ่งสำคัญที่นี่ ไม่เคยทำเช่นนี้ในสคริปต์ สำหรับข้อมูลเพิ่มเติมอ่านข้อผิดพลาดทุบตี
pawel7318

@ pawel7318 ลิงก์ที่คุณให้ในขณะที่คำแนะนำที่ดีเยี่ยมดูเหมือนจะไม่ใช้กับคำสั่งที่ให้ไว้ข้างต้น กรณีขอบเดียวที่ฉันเห็นด้วยคำสั่งนี้คือ: (1) ไม่ตรวจสอบว่าไฟล์เป้าหมายมีอยู่แล้วหรือว่าไฟล์เป้าหมายมีอยู่แล้วเป็นไดเรกทอรี (ซึ่งจะคัดลอกไฟล์ลงในไดเรกทอรีรักษาชื่อปัจจุบันของมัน) และ (2) หากมีไฟล์จำนวนมากที่การขยายตัวของ glob ไม่เหมาะสมกับบรรทัดคำสั่งเดียว
Wildcard

1
ฉันได้รับสิ่งนี้: cp /usr/local/lib/libboost* /usr/local/lib/libboost*ด้วยการตรวจสอบเสียงสะท้อน
Tomáš Zato

8

เมื่อต้องการทำสิ่งนี้อย่างมีประสิทธิภาพด้วยไฟล์จำนวนมากจะเป็นการดีกว่าที่จะหลีกเลี่ยงการเริ่มต้นcpกระบวนการที่แตกต่างกันสำหรับแต่ละไฟล์ วิธีหนึ่งคือการคัดลอกแล้วเปลี่ยนชื่อโดยใช้prename( renameจะเชื่อมโยงกับสิ่งนี้ตามค่าเริ่มต้นบน Distros ที่ใช้ Debian) ใช้สิ่งนี้และ Linux mktemp:

tmp=$(mktemp -d --tmpdir=.)
cp ABC.* "$tmp"
prename "s:$tmp/ABC:DEF:" "$tmp/"*
rmdir "$tmp"

ปรับปรุง

จริงๆแล้วpaxอาจเป็นวิธีที่ดีกว่าในการไปที่นี่:

pax -rws '/^ABC/DEF/' ABC.* .

น่าเสียดายที่แม้ว่าpaxทั้ง POSIX และ Linux Standard Base จะมี distros บางส่วนเป็นค่าเริ่มต้น


สัมผัสที่ดีโดยใช้: เป็นตัวคั่นเพื่อหลีกเลี่ยงการหลบหนี
Clayton Stanley

5

tar จะทำสิ่งนี้ให้คุณอย่างรวดเร็วจริงๆ

ทดสอบ

ครั้งแรกที่ฉันสร้าง 2 ไดเรกทอรีและ 10 ไฟล์:

% mkdir test1 test2 ; cd test1
% for n in `seq 1 10` ; do touch ABC.file$n ; done
% ls

> ABC.file1   ABC.file2  ABC.file4  ABC.file6  ABC.file8
> ABC.file10  ABC.file3  ABC.file5  ABC.file7  ABC.file9

จากนั้นฉันก็คัดลอก

% tar -cf - ./* |\ 
    tar -C../test2 --transform='s/ABC/DEF/' -xf -
% ls ../test2

> DEF.file1   DEF.file2  DEF.file4  DEF.file6  DEF.file8
> DEF.file10  DEF.file3  DEF.file5  DEF.file7  DEF.file9

แปลง

ดังนั้น GNU tarจะยอมรับการsed --transform=EXPRESSIONเปลี่ยนชื่อไฟล์ สิ่งนี้สามารถเปลี่ยนชื่อไฟล์ได้เพียงบางไฟล์เท่านั้น ตัวอย่างเช่น

% tar -cf - ./* |\ 
    tar -C../test2 --transform='s/ABC\(.*[0-5]\)/DEF\1/' -xf -
% ls ../test2

> ABC.file6  ABC.file8  DEF.file1   DEF.file2  DEF.file4
> ABC.file7  ABC.file9  DEF.file10  DEF.file3  DEF.file5

นั่นคือข้อดีอย่างหนึ่ง

กระแส

พิจารณาด้วยว่านี่เป็นเพียงสองtarกระบวนการ - และนั่นจะไม่เปลี่ยนแปลงโดยไม่คำนึงถึงจำนวนไฟล์ของคุณ

tar | tar

tarได้รับการปรับปรุงให้ดีที่สุดเท่าที่คุณต้องการ สิ่งนี้จะไม่นับการโต้แย้งปัญหาหรือกระบวนการลูกที่ควบคุมไม่ได้ นี่เป็นเพียงA> Bเสร็จแล้ว

อาร์กิวเมนต์

ฉันใช้ข้อโต้แย้งที่แตกต่างกัน 7 ข้อระหว่างทั้งสองtarกระบวนการของฉันที่นี่ สิ่งที่สำคัญที่สุดมีอยู่ที่นี่ก่อน:

-stdout / stdin - สิ่งนี้แจ้งtarว่ามันจะสตรีมไม่ว่าจะเป็นอินพุทหรือเอาท์พุทไปยังหรือจากการstdin/stdoutที่มันจะตีความอย่างถูกต้องขึ้นอยู่กับว่ามันกำลังสร้างหรือแยกไฟล์เก็บถาวร

-cสร้าง - สิ่งนี้บอกtarให้สร้างการเก็บถาวร อาร์กิวเมนต์ถัดไปที่tarคาดหวังคือ ...

-fไฟล์ - เราระบุว่าtarจะทำงานกับfileวัตถุมากกว่าอุปกรณ์เทปหรืออะไรก็ตาม และไฟล์ที่จะทำงานร่วมกับตามที่ระบุไว้ข้างต้นคือstdin/stdout- ในคำอื่น ๆ |pipeของเรา

./*ทั้งหมด $ PWD / ไฟล์ - ไม่มากเกินไปที่จะอธิบายที่นี่ยกเว้นว่าอาร์กิวเมนต์เก็บมาก่อนดังนั้นแล้ว-./*

... และอีกด้านหนึ่งของ|pipe...

-Cchange directory - สิ่งนี้แจ้งtarว่าจำเป็นต้องเปลี่ยนเป็นไดเร็กทอรีที่ฉันระบุก่อนทำการดำเนินการอื่นใดดังนั้นจึงควรแก้ไขcd ../test2ก่อนที่จะทำการแตกไฟล์

--transform='s/ed/EXPR/'- ดังที่ได้กล่าวไปแล้วการเปลี่ยนชื่อทำได้ แต่เอกสารระบุว่าสามารถใช้ใด ๆแสดงออกหรือsed//flag

-xแยก - หลังจากtarการเปลี่ยนแปลงไปยังไดเรกทอรีเป้าหมายของเราและรับคำแนะนำในการเปลี่ยนชื่อของเราเราแนะนำให้เริ่มแตกไฟล์ทั้งหมดลงในไดเรกทอรีปัจจุบันจาก-f - |pipeไฟล์เก็บถาวร ไม่มีความลึกลับ


1
นี่คือpaxวิธีแก้ปัญหาสำหรับคำถามนี้ ฉันจะเพิ่มเข้าไปในคำตอบของฉัน แต่ฉันคิดว่ามันเป็นความเหมาะสมดีกว่าที่นี่ -pax -rws '/^ABC/DEF/' ABC.* .
แกรม

@ Graeme - woah - นั่นเป็นวิธีที่ดีกว่า! มนุษย์ก็ชนะนรกด้วยการเปลี่ยนชื่อมุกด้วย! คุณควรใส่ในคำตอบของคุณ - paxเป็น POSIX ระบุ - paxด้วยเหตุนี้
mikeserv

paxอาจเป็น POSIX แต่ก็ไม่ค่อยติดตั้งตามค่าเริ่มต้น
แกรม

4

หากคุณไม่รังเกียจการใช้เครื่องมือมาตรฐานที่น้อยกว่าฉันขอแนะนำให้ใช้mmv (การย้ายมวล) ซึ่งเขียนขึ้นสำหรับงานประเภทนี้ การใช้mcp(สำเนาจำนวนมาก) ซึ่งเป็นส่วนหนึ่งของชุดคุณสามารถทำได้

mcp "ABC.*" "DEF.#1"

ไม่ง่ายเลยที่จะหาแพ็คเกจดาวน์โหลด ปัจจุบันแพคเกจ Debian (ซึ่ง Arch นอกจากนี้ยังใช้ใน AUR) เพื่อรวบรวมที่บ้านสามารถพบได้ที่นี่


ติดตั้งบน Ubuntu 15.10 ออกจากกล่องapt-get install mmv
Thufir

2

ใน zsh ใส่บรรทัดต่อไปนี้ใน.zshrc:

autoload -U zmv
alias zmv='noglob zmv'
alias zcp='zmv -C'
alias zln='zmv -L'

จากนั้นในบรรทัดคำสั่งคุณสามารถเรียกใช้

zcp 'ABC(.*)' 'DEF$1'

หรือเพียงแค่

zcp -W ABC.* DEF.*

ในเชลล์อื่นตราบใดที่คุณติดตั้ง zsh ไว้:

zsh -c 'autoload zmv; noglob zmv -CW ABC.* DEF.*'

1

คุณสามารถทำได้:

for i in ABC.*; do cp {ABC,DEF}."${i#*.}"; done

อาจมีสิ่งที่ฉันไม่เห็น แต่ฉันจะตั้งหลายปลายทางได้อย่างไร ฉันใช้การวนรอบเพื่อให้ได้แต่ละอัน ฉันทดสอบโค้ดล่วงหน้าและใช้งานได้ตามคาดดังนั้นฉันขอขอบคุณคำอธิบายของคุณ
Sara Fauzia

นั่นคือสิ่งที่ไม่ดีของฉันฉันอ่านคำตอบของคุณผิด :-)
Chris Down

ฉันจะอ่าน"${i#*.}"บิตได้อย่างไร?
dumbledad

-1

คุณสามารถทำได้: http://www.projectik.eu/index.php/programovanie/linux/item/243-linux-kopirovanie-suborov-vo-vlakne นี่คือตัวอย่าง


1
ยินดีต้อนรับสู่ Unix & Linux! ในขณะที่สิ่งนี้อาจตอบคำถามในทางทฤษฎีมันก็ควรจะรวมส่วนสำคัญของคำตอบที่นี่และให้ลิงค์สำหรับการอ้างอิง
terdon
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.