เปลี่ยนชื่อไฟล์หลายรายการโดยใช้ Bash scripting


27

ฉันต้องการเปลี่ยนชื่อหลายไฟล์ในไดเรกทอรีเดียวกันโดยใช้ Bash scripting ชื่อของไฟล์มีดังนี้:

file2602201409853.p
file0901201437404.p  
file0901201438761.p  
file1003201410069.p  
file2602201410180.p

ฉันต้องการเปลี่ยนชื่อเป็นรูปแบบต่อไปนี้:

file2503201409853.p
file2503201437404.p  
file2503201438761.p  
file2503201410069.p  
file2503201410180.p

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

for file in cmpsms*2014*.p; do
    mv "$file" "${file/cmpsms*2014*.p/cmpsms25032014*.p}"
done

แต่ฉันไม่สามารถเปลี่ยนชื่อไฟล์ได้ ผมทำอะไรผิดหรือเปล่า?



2
คุณไม่สามารถมีนิพจน์รูปแบบทางด้านขวามือของนิพจน์การแทนที่การขยายพารามิเตอร์ คุณไม่คาดหวังอะไรที่จะเป็นที่ว่า*คืออะไร?
kojiro

@ Kiwy คำถามนั้นเกี่ยวกับการลบบางส่วนของชื่อไฟล์ Ergo ซ้ำอย่างสงสัยอย่างมาก
CVn

2
ครั้งต่อไปโปรดอธิบายการเปลี่ยนแปลงชื่อไฟล์ที่คุณต้องการ (ฉันต้องดูสิ่งนี้ในระหว่างที่รอก่อนที่จะเห็นความแตกต่างและความคล้ายคลึงกัน) ตัวอย่างนั้นดี แต่คำอธิบายและตัวอย่างนั้นดีกว่า
CVn

คำตอบ:


42

คุณมีสิทธิ์พิจารณาเปลี่ยนชื่อก่อน ไวยากรณ์นั้นแปลกเล็กน้อยถ้าคุณไม่คุ้นเคยกับการทำ regexes แต่มันเป็นเส้นทางที่เร็วที่สุด / สั้นที่สุดเมื่อคุณรู้ว่าคุณกำลังทำอะไรอยู่:

rename 's/\d{4}/2503/' file*

ซึ่งตรงกับตัวเลข 4 ตัวแรกและสลับเป็นตัวเลขที่คุณระบุ

และสายรัดทดสอบ ( -vnหมายถึงให้ละเอียด แต่อย่าทำอะไรเลย) โดยใช้ชื่อไฟล์ของคุณ:

$ rename 's/\d{4}/2503/' file* -vn
file0901201437404.p renamed as file2503201437404.p
file0901201438761.p renamed as file2503201438761.p
file1003201410069.p renamed as file2503201410069.p
file2602201409853.p renamed as file2503201409853.p
file2602201410180.p renamed as file2503201410180.p

8
โปรดทราบว่านี่คือการเปลี่ยนชื่อ Perl บน Debian และอนุพันธ์ (Ubuntu, Mint, …) บน Linux ดิสทริบิวชันอื่นrenameเป็นเครื่องมือเปลี่ยนชื่อไฟล์ที่แตกต่างอย่างสิ้นเชิง (ซึ่ง Debian จัดส่งเป็นrename.ul)
Gilles 'หยุดชั่วร้าย'

หากการกระจายของคุณขาดเครื่องมือดังกล่าวให้ดูที่ @Michael Campbell คำตอบ ฉันคิดว่าผู้แทนจำหน่ายทุกคนแทนที่ค่าเริ่มต้นrenameเช่นเดเบียนได้
Astery

25

สิ่งนี้ควรทำเคล็ดลับ:

for f in file*; do mv $f ${f/${f:4:8}/25032014}; done

มันแทนที่สตริงซึ่งทำให้ตัวอักษรที่ 4 และ 12 เป็น "25032014"


นี้for f in file*; do mv $f ${f/${f:4:4}/2503}; doneทำงานยัง
Avinash Raj

เยี่ยมมาก หากคุณเพียงต้องการที่จะทำคำปกติสำหรับการแทนที่คำมันทำงานเหมือน sed เช่นfor f in *Huge*; do mv $f ${f/Huge/Monstrous}; done
Eric

1
@Eric - ฉันโพสต์คำตอบของคุณเป็นทางเลือกเพราะฉันคิดว่ามันชัดเจนและสง่างาม หากคุณต้องการโพสต์เป็นคำตอบ - ฉันจะลบของฉัน ขอบคุณ!
Yehosef


มันทำให้ฉันมีข้อผิดพลาด: "mv: เป้าหมาย 'FILE_NAME' ไม่ใช่ไดเรกทอรี"
Aubrey

10

นี่เป็นคำตอบจริง ๆ ของ @ Eric จากด้านบน - แต่มันเป็นคำตอบที่สง่างามดังนั้นฉันจึงประกาศใหม่เป็นคำตอบที่เหมาะสมเพื่อดึงดูดความสนใจมากขึ้น

for f in *Huge*; do mv $f ${f/Huge/Monstrous}; done

1
ptrn='file[0-9][0-9][0-9][0-9]2014[0-9][0-9][0-9][0-9][0-9].p'
path=/dir
( set -- "${path}/"${ptrn} ; for f ; do {
    echo "mv ${path}/${f} \
        ${path}/file25032014${f#2014}" 
} ; done )

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


1

วิธีการเนทีฟแบบง่าย ๆ โดยไม่ต้องวนซ้ำด้วยการข้ามผ่านไดเรกทอรี :

find -type f | xargs -I {} mv {} {}.txt

มันจะเปลี่ยนชื่อทุกไฟล์ในสถานที่

และด้านล่างเป็นตัวอย่างการทำงานพร้อมการขนาน :

find -name "file*.p" | parallel 'f="{}" ; mv -- {} ${f:0:4}2503${f:8}'

มันเป็นวิธีแรกที่ง่ายในการจินตนาการทางออกที่ดีขึ้น หากคุณต้องการให้คำสั่งทำงานให้ทำ:
dtrckd

find -type f -name "file*.p" | parallel 'ext="{}" ; mv -- {} ${ext:0:4}2503${ext:8}'
dtrckd

0

หากคุณพบว่าคุณทำสิ่งนี้เป็นอย่างมากให้ค้นหา "rename.pl" เป็นสคริปต์ Perl แต่ให้คุณป้อนรหัส Perl ได้ (เช่นนิพจน์ ///) และจะทำการเปลี่ยนชื่อจำนวนมากตามนิพจน์หรือรหัสนั้น

มีรุ่นพื้นฐานอยู่ที่นี่: http://stackoverflow.org/wiki/Rename.pl แต่มีเวอร์ชันอื่นที่ลอยอยู่บนอินเทอร์เน็ต มันเป็นรอบสำหรับทุกวัยและทุกวัยและทุกวัย

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