ฉันจะเปลี่ยนนามสกุลของหลายไฟล์ได้อย่างไร


166

ผมอยากจะเปลี่ยนนามสกุลไฟล์จากไป*.txt *.textฉันพยายามใช้basenameคำสั่ง แต่ฉันมีปัญหาในการเปลี่ยนมากกว่าหนึ่งไฟล์

นี่คือรหัสของฉัน:

files=`ls -1 *.txt`

for x in $files
do
    mv $x "`basename $files .txt`.text"
done

ฉันได้รับข้อผิดพลาดนี้:

basename: too many arguments Try basename --help' for more information

ความคิดบางอย่างที่peteryu.ca/tutorials/shellscripting/batch_renameด้วย
Nemo

คำตอบ:


175

ส่งตรงจากWiki ของ Greg :

# เปลี่ยนชื่อทั้งหมด * .txt เป็น * .text
สำหรับ f ใน * .txt; ทำ
    mv - "$ f" "$ {f% .txt} .text"
เสร็จแล้ว

นอกจากนี้ยังดูรายการเกี่ยวกับเหตุผลที่คุณไม่ควรแยกls

แก้ไข: ถ้าคุณต้องใช้basenameไวยากรณ์ของคุณจะเป็น:

สำหรับ f ใน * .txt; ทำ
    mv - "$ f" "$ (basename -" $ f ".txt) .text"
เสร็จแล้ว

48
มีการใช้ไวยากรณ์ Bash ขั้นสูงเล็กน้อยโดยไม่มีคำอธิบาย ฉันต้องใช้ Google หลาย ๆ อย่างเพื่อทำความเข้าใจสิ่งนี้อย่างเต็มที่ เพื่อช่วยให้คนอื่น ๆ ในตำแหน่งของฉันที่นี่มีการอ้างอิงบางอย่างเกี่ยวกับglobs (คน*.txtไวยากรณ์)ที่ประคู่เปลือย--และการใช้สัญลักษณ์% ภายในที่${}สร้าง จนถึงตอนนี้ฉันไม่เคยเจอสองคนหลังและไม่ทราบว่าเกิดอะไรขึ้นกับอดีต
Mark Amery

3
ดูคำตอบของ Matthias Braun ด้านล่าง - ง่ายกว่ามากทำสิ่งเดียวกันให้สำเร็จ
btk

10
สายการบินfor f in *.txt; do mv -- "$f" "${f%.txt}.text"; done
Marçal Juan

1
คุณหายไป หลังจากข้อความ ".
Pétur Ingi Egilsson

2
@ PéturIngiEgilssonในบรรทัดที่สอง? ไม่ไม่จำเป็น
jasonwryan

132

นี่คือวิธีที่ฉันเปลี่ยนนามสกุลไฟล์ทั้งหมดในไดเรกทอรีปัจจุบันบน Debian

rename "s/oldExtension/newExtension/" *.txt

(นี่คือrenameคำสั่งPerl ไม่ใช่คำสั่งutil-linuxเดียวดูที่เหตุใดยูทิลิตี้การเปลี่ยนชื่อบน Debian / Ubuntu แตกต่างจากอันอื่นในดิสทริบิวชันอื่น ๆ เช่น CentOS? )


10
ง่ายกว่าคำตอบที่ยอมรับขอบคุณมาก!
btk

8
สำหรับ Mac ฉันสามารถbrew install renameและใช้งานได้
Monkpit

3
ด้วย fish shell คุณสามารถทำการrename "s/oldExtension/newExtension/" **.txtเปลี่ยนชื่อ * .txt ทั้งหมดแบบเรียกซ้ำ
Palmstrom

3
footxt.txtนี้จะล้มเหลว ใช้สิ่งนี้แทน: unix.stackexchange.com/questions/19654/…
wisbucky

7
เมื่อไฟล์ของคุณไม่มีส่วนขยายใด ๆ และคุณต้องการที่จะเพิ่ม:rename 's/$/.txt/' *
mkataja

34

คำสั่งง่ายๆคำสั่งrenameจากutil-linuxจะทำเพื่อคุณโดยจะแทนที่ "txt" เป็น "text" ทุกครั้งในการจับคู่ไฟล์ทั้งหมด "* .txt":

rename txt text *.txt

4
renameเปลี่ยนการเกิดขึ้นครั้งแรกเพื่อให้ดีขึ้นrename .txt .textแต่สิ่งนี้ยังคงไม่ทำงาน (เช่นจะเปลี่ยนfoo.txtx.bar.txtเป็นfoo.textx.bar.txt)
Gilles

12
ควรสังเกตว่าไม่ใช่ทุกระบบที่มีการเปลี่ยนชื่อรุ่นเดียวกัน บนเดเบียนและเพื่อน ๆrenameคำสั่งนั้นเป็นจริงperl-renameและใช้ perl regexes rename 's/.txt/.text/' *.txtการที่คำสั่งเทียบเท่าจะเป็น: ผู้คนควรตรวจสอบman renameบนระบบของพวกเขาเพื่อค้นหาสิ่งที่พวกเขามี
evilsoup

@evilsoup นั้นเป็นกรณีของ OSX, ขอบคุณ
Davi Lima

สิ่งนี้สามารถใช้งานได้กับ Cygwin (Windows)
andy

27
rename "s/oldExtension/newExtension/" *.txt

ด้านบนทำงานได้ดี แต่ จำกัด เฉพาะไดเรกทอรีปัจจุบัน ลองใช้คำสั่งด้านล่างซึ่งยืดหยุ่นด้วยไดเรกทอรีย่อย มันจะเปลี่ยนชื่อ.txtไฟล์ทั้งหมดภายใต้โครงสร้างไดเรกทอรีด้วยส่วนขยายใหม่

find . -name "*.txt" -exec rename 's/.txt$/.newext/' {} \;

2
renameสามารถจัดการกับไฟล์หลาย ๆ ไฟล์เป็นอาร์กิวเมนต์คุณสามารถเพิ่มความเร็วของสิ่งต่าง ๆ ได้อย่างมากมายโดยใช้+แทน\;หากมีไฟล์จำนวนมาก
Anthon

ถึงกระนั้นก็เป็นตัวเลือกที่มีประโยชน์เนื่องจาก "* .txt" สามารถยกเลิกการลงทะเบียนรายการอาร์กิวเมนต์ขนาดใหญ่ที่เชลล์ไม่สนับสนุน
Roman Shapovalov

1
"s / oldExtension / newExtension /" footxt.txtจะล้มเหลว ใช้สิ่งนี้แทน: unix.stackexchange.com/questions/19654/…
wisbucky


9

คำตอบอ้างอิงที่นี่s/oldExtension/newExtension/ผิด หากคุณใช้s/txt/text/คุณจะแปลงfootxt.txtเป็นfootext.txtซึ่งไม่ใช่สิ่งที่คุณต้องการ แม้ว่าคุณจะใช้s/.txt/.text/ที่จะแปลงไปfootxt.txtfo.text.txt

คุณต้องใช้\.เพื่อให้ตรงกับระยะเวลา ( .จะตรงกับตัวละครใด ๆ ) และมีการต่อท้าย$เพื่อให้ตรงกับจุดสิ้นสุดของบรรทัด เฉพาะสิ่งนี้จะตรงกับส่วนขยายอย่างถูกต้อง

rename 's/\.txt$/.text/' *.txt

rename 's/\.old$/.new/' *.old

7

ขึ้นอยู่กับคำตอบที่ @Prince จอห์นเวสลีย์ที่นี่เป็นสคริปต์ทุบตีง่ายสำหรับการเปลี่ยนนามสกุลไฟล์ทั้งหมดในไดเรกทอรีปัจจุบันจากการext1 ext2เอาท์พุทชื่อของไฟล์ที่ถูกเปลี่ยนชื่อ

#!/bin/bash
for f in *.$1
do
    [ -f "$f" ] && mv -v "$f" "${f%$1}$2"
done

ตัวอย่างการใช้งาน (สมมติว่าชื่อของสคริปต์คือchange-ext):

change-ext ext1 ext2

การเปลี่ยนนามสกุลของไฟล์ในไดเรกทอรีซ้ำเปลี่ยนบรรทัดที่สอง ( for...) มีสองบรรทัด: และshopt -s globstar for f in **/*.$1ต้องการ Bash 4+
Dennis Golomazov


3

สมมติว่าไฟล์ของคุณกระจัดกระจายในไดเรกทอรีต่าง ๆ สมมติว่า dirx เป็นไดเรกทอรีหลักของคุณสิ่งนี้สามารถทำงานได้โดยใช้ find:

for f in `find /dirx -iname '*.txt' -type f -print`;do  mv "$f" ${f%.txt}.text; done

tcsh ..
Josef Klimuk


2

เมื่อคุณ

ไม่มีส่วนขยายสำหรับไฟล์ต้นฉบับ

และส่วนขยายเป้าหมายคือ. textคุณต้องทำเช่นนี้ -

for f in *; do mv -- "$f" "${f%.\*}.text"; done

1
สคริปต์ทุบตีที่ยอดเยี่ยม ใช้งานได้ดี! for f in *.html; do mv -- "$f" "${f%.\*}.pug"; done
TamusJRoyce

1

ในกรณีที่คุณต้องการที่จะรู้ว่ามีอะไรผิดพลาดในรุ่นของคุณ: คุณใช้$filesแทน$xในคำสั่ง basename ดังนั้นควรใช้งานได้ (ยังไม่ทดลอง):

for x in *.txt
do
  mv "$x" "`basename '$x' .txt`.text"
done
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.