วิธีการเปลี่ยนชื่อไฟล์หลายไฟล์โดยแทนที่สตริงในชื่อไฟล์? สายนี้มี“ #”


42

https://serverfault.com/questions/70939/how-to-replace-a-text-string-in-multiple-files-in-linux

https://serverfault.com/questions/228733/how-to-rename-multiple-files-by-replacing-word-in-file-name

https://serverfault.com/questions/212153/replace-string-in-files-with-certain-file-extension

https://serverfault.com/questions/33158/searching-a-number-of-files-for-a-string-in-linux

บทความที่กล่าวถึงเหล่านี้ล้วนตอบคำถามของฉัน อย่างไรก็ตามไม่มีพวกเขาทำงานให้ฉัน ฉันสงสัยว่าเป็นเพราะสตริงที่ฉันพยายามแทนที่มีหมายเลขอยู่ มีวิธีพิเศษในการแก้ไขปัญหานี้หรือไม่?

ฉันมีไฟล์รูปภาพที่มีéแทนที่ด้วย # U00a9 ระหว่างการย้ายข้อมูลไซต์ มีลักษณะเช่นนี้:

Lucky-#U00a9NBC-80x60.jpg
Lucky-#U00a9NBC-125x125.jpg
Lucky-#U00a9NBC-150x150.jpg
Lucky-#U00a9NBC-250x250.jpg
Lucky-#U00a9NBC-282x232.jpg
Lucky-#U00a9NBC-300x150.jpg
Lucky-#U00a9NBC-300x200.jpg
Lucky-#U00a9NBC-300x250.jpg
Lucky-#U00a9NBC-360x240.jpg
Lucky-#U00a9NBC-400x250.jpg
Lucky-#U00a9NBC-430x270.jpg
Lucky-#U00a9NBC-480x240.jpg
Lucky-#U00a9NBC-600x240.jpg
Lucky-#U00a9NBC-600x250.jpg
Lucky-#U00a9NBC.jpg

และฉันต้องการเปลี่ยนมันเป็นอย่างนี้:

Lucky-safeNBC-80x60.jpg
Lucky-safeNBC-125x125.jpg
Lucky-safeNBC-150x150.jpg
Lucky-safeNBC-250x250.jpg
Lucky-safeNBC-282x232.jpg
Lucky-safeNBC-300x150.jpg
Lucky-safeNBC-300x200.jpg
Lucky-safeNBC-300x250.jpg
Lucky-safeNBC-360x240.jpg
Lucky-safeNBC-400x250.jpg
Lucky-safeNBC-430x270.jpg
Lucky-safeNBC-480x240.jpg
Lucky-safeNBC-600x240.jpg
Lucky-safeNBC-600x250.jpg
Lucky-safeNBC.jpg

UPDATE:

ตัวอย่างเหล่านี้ทั้งหมดเริ่มต้นด้วย "LU00a9ucky แต่นี่คือภาพจำนวนมากที่มีชื่อแตกต่างกันฉันแค่กำหนดเป้าหมายส่วน" # U00a9 "ของสตริงเพื่อแทนที่ด้วย" ปลอดภัย "


3
คุณลองทำอะไรจริง ๆ ฉันเห็นว่าคุณเชื่อมโยงกับคำถามสองสามข้อและบอกว่าพวกเขาล้มเหลว แต่พวกเขาล้มเหลวอย่างไร IMO ตัวอย่างที่ดีที่สุดใช้renameคำสั่ง rename -n 's/#/safeNBC/' *.jpgฉันสงสัยว่าการเปลี่ยนชื่อของคุณจะเป็นง่ายๆเป็น
Zoredache

ฉันพยายามrename -n 's/#U00a9/safe/' *.jpgและคำสั่งนั้นได้รับการยอมรับ แต่ไม่มีการเปลี่ยนแปลงเกิดขึ้น

แน่นอนว่าคุณจะได้เห็นจากเอกสารที่คุณตรวจสอบอย่างแน่นอนว่า-nเป็นno actตัวเลือก ซึ่งช่วยให้คุณดูว่ามันใช้งานได้จริงหรือไม่ก่อนใช้งานจริง ผลลัพธ์บนหน้าจอแสดงชื่อใหม่ที่เป็นไปได้อย่างถูกต้องหรือไม่?
Zoredache

ฉันขอโทษที่ฉันคัดลอกและวางตัวอย่างของคุณโดยไม่ให้ความสนใจอย่างเต็มที่ฉันทำคำสั่งเปลี่ยนชื่อโดยไม่ใช้ -n ฉันเชื่อว่า @DTK แก้ไขปัญหาฉันไม่ได้หนี #

การแทนที่สตริงในชื่อไฟล์บน MacOS: superuser.com/questions/152627/…
Anton Tarasenko

คำตอบ:


64

ในการแทนที่#ด้วยsomethingelseชื่อไฟล์ในไดเรกทอรีปัจจุบัน (ไม่เรียกซ้ำ) คุณสามารถใช้ยูทิลิตี้เปลี่ยนชื่อ GNU :

rename  's/#/somethingelse/' *

ตัวอักษรเช่นจะต้องหนีไปกับ-\

สำหรับกรณีของคุณคุณต้องการใช้

rename 's/#U00a9/safe/g' *

โปรดทราบว่าหากคุณต้องการใช้งานไฟล์บางตัวเท่านั้น*.jpgเช่นปรับเฉพาะอินพุตสุดท้ายเพื่อให้ตรงกับส่วนที่เลือก:

rename 's/#U00a9/safe/g' *.jpg

หากต้องการทำการทดสอบก่อนเปลี่ยนชื่อไฟล์จริงให้ใช้การ-nตั้งค่าสถานะ:

demo/> ls                               
Lucky-#U00a9NBC-125x125.jpg  
Lucky-#U00a9NBC-150x150.jpg 

demo/> rename -n 's/#U00a9/safe/g' *.jpg
rename(Lucky-#U00a9NBC-125x125.jpg, Lucky-safeNBC-125x125.jpg)
rename(Lucky-#U00a9NBC-150x150.jpg, Lucky-safeNBC-150x150.jpg)

สำหรับ OS X, เปลี่ยนชื่อ GNU สามารถติดตั้งใช้Homebrewbrew install rename :


สิ่งนี้ไม่ทำงานบนเครื่องของฉัน (Arch Linux) แต่คำตอบของ mik นั้น
marcvangend

@marcvangend renameคุณใช้เวอร์ชั่นไหน # sudo pacman -S perl-renameจะติดตั้งเวอร์ชัน perl ซึ่งมีประสิทธิภาพมากกว่าและอาจเพียงพอที่จะทำให้คำตอบนี้ใช้ได้สำหรับคุณ
John Gowers

@JohnGowers ขอบคุณ! ฉันไม่ทราบว่ามีสองรุ่น ในระบบของฉันrename --versionส่งคืนrename from util-linux 2.29.2เพื่อให้ไม่ใช่รุ่น perl
marcvangend

5
มีสองrenameยูทิลิตี้ทั่วไปแต่ไม่มีทั้งคู่ถูกพัฒนาโดย GNU: การแจกแจงแบบเดเบียนรวมถึงrenameยูทิลิตี้พร้อมกับแพกเกจ Perl ของพวกเขาในขณะที่การแจกจ่ายที่ใช้ Red Hat ใช้renameยูทิลิตีจากutil-linuxLinux Kernel Organization ลิงก์ของคุณไปยังฟังก์ชันrename C จากไลบรารีมาตรฐานของ GNU
Anthony G - ความยุติธรรมสำหรับโมนิก้า

2
ในคำตอบนี้ทำไมเราต้องเขียน/gด้วยrename 's/#U00a9/safe/g' *
Nikhil

21

ค้นหารายชื่อไฟล์แล้วแทนที่คำหลัก ด้านล่างเป็นตัวอย่าง

find . -name '*jpg' -exec bash -c ' mv $0 ${0/\#U00a9NBC/safeNBC}' {} \;

1
คุณต้องใส่เครื่องหมายคำพูดคู่รอบmvอาร์กิวเมนต์ของคุณในกรณีที่มีช่องว่างในชื่อ
หยุดทำร้ายโมนิก้า

ฉันต้องการแทนที่ไฟล์ทั้งหมด * _spec.rb เป็น * _controller_spec.rb และโซลูชันของคุณใช้ได้สำหรับฉัน Thanx
เจได

18

นี่ไม่ใช่เรื่องยากเพียงให้แน่ใจว่าได้หลีกเลี่ยง octothorpe (#) ในชื่อด้วยการใส่ reverse-slash (\)

find . -type f -name 'Lucky-*' | while read FILE ; do
    newfile="$(echo ${FILE} |sed -e 's/\\#U00a9/safe/')" ;
    mv "${FILE}" "${newfile}" ;
done 

คำอธิบายของคุณสมเหตุสมผลแล้วหนี#เสียงเหมือนสิ่งที่ฉันต้องการ ฉันไม่เห็นแบ็กสแลชในตัวอย่างของคุณ ควรมีลักษณะเช่นนี้: s/\#U00a9/safe/

@ LeonFrancisShelhamer จับดี มันกลืนแบ็กสแลช ฉันจะแก้ไข

17

หากต้องการหลบหนี#จากเชลล์ให้ใช้เครื่องหมายคำพูดเดี่ยว ( '#'), เครื่องหมายคำพูดคู่ ( "#") หรือเครื่องหมายแบ็กสแลช ( \#)

ที่ง่ายที่สุดในกรณีของคุณคือการใช้renameคำสั่ง (ถ้ามี):

rename '#U00a9' safe *.jpg

2
ขอบคุณ ในขณะที่คำตอบที่โหวตสูงสุด ( rename 's/#/somethingelse/' *) ไม่ทำงานบนเครื่องของฉัน (Arch Linux) อันนี้ก็ทำได้
marcvangend

1
ใช้งานได้โดยใช้คำสั่งเปลี่ยนชื่อจาก util-linux
imclean

10

ไม่แน่ใจว่าจะอยู่ใน sed อย่างไร แต่คุณสามารถลองสิ่งนี้ใน bash shell:

for f in Lucky-#U00a9NBC-*.jpg; do mv -v "$f" "${f/#U00a9/safe}"; done;

คำอธิบาย:

  1. วนซ้ำทุกชื่อไฟล์ที่ตรงกับ glob (Lucky- # U00a9NBC - *. jpg)
  2. เปลี่ยนชื่อไฟล์โดยใช้คำสั่ง move (mv)
  3. ใช้การแทนค่าพารามิเตอร์ดั้งเดิมของ bash $ {var / Pattern / Replacement} เพื่อสร้างชื่อใหม่ ("$ {f / # U00a9 / safe}")

ข้อมูลเพิ่มเติมเกี่ยวกับการทดแทนพารามิเตอร์ (ซึ่งเป็น IMO ที่ด้อยค่าอย่างมาก): http://www.tldp.org/LDP/abs/html/parameter-substitution.html


แม้ว่ารหัสนี้อาจตอบคำถาม แต่ก็ไม่มีประโยชน์มากนัก การอธิบายว่าวิธีแก้ปัญหาจะช่วยเพิ่มประโยชน์และคุณค่าระยะยาวของคำตอบได้อย่างไร
Anthony G - ความยุติธรรมสำหรับโมนิก้า

เพิ่มคำอธิบายแบบแนะนำและอ่านเพิ่มเติมตามความคิดเห็นของ Anthony
Gregory Patmore

1

ตัวอย่างข้างต้นไม่ได้ทำงานกับระบบของฉัน (CentOS 5.6) ดังนั้นฉันจึงพบคำสั่ง (อาจเป็นระบบเฉพาะ) ที่ใช้งานได้ (หมายเหตุ: จำเป็นต้องหลบหนี '#' ด้วย\บรรทัดคำสั่ง):

rename \#U00a9 safe *.jpg

[ยัง: ฉันยังไม่มีชื่อเสียงพอที่จะแสดงความคิดเห็นดังนั้นในการตอบสนองคำถามของ Nikhil เกี่ยวกับการใช้งาน/gในrename 's/old_string/new_string/g'(โพสต์ในความคิดเห็นสำหรับคำตอบอื่นข้างต้น):

ใช้gโมดิฟายเออร์เพื่อทำการทดแทน 'ทั่วโลก' (นั่นคือเพื่อแทนที่ new_string สำหรับ old_string หลายครั้งเมื่อ old_string เกิดขึ้น) นี้ไม่ควรเป็นสิ่งที่จำเป็นในคำตอบของฉันเพราะจะถูกนำไปใช้กับไฟล์ทั้งหมดที่ระบุไว้กับrename *ดูhttps://www.computerhope.com/unix/rename.htmสำหรับคำอธิบายที่กระชับเกี่ยวกับสิ่งนี้และตัวดัดแปลงอื่น ๆ ]


แก้ไข; ระบบปฏิบัติการที่ได้รับจาก Fedora เช่น CentOS มีเวอร์ชันที่แตกต่างจากrenameระบบปฏิบัติการ Debian ดูunix.stackexchange.com/a/238862/135943 CentOS 5.6 ค่อนข้างเก่าและผมขอแนะนำให้คุณอัพเกรด
Wildcard

ขอบคุณสำหรับคำอธิบาย + ลิงก์ ระบบปฏิบัติการที่ล้าสมัยอยู่ในระหว่างการทำงานดังนั้นจึงไม่ขึ้นอยู่กับฉันที่จะอัปเกรด :) แต่มีการสร้างคลัสเตอร์ใหม่และเราจะอัปเกรดเมื่อเราย้าย ...
Ezra Citron

0

นี่คือโซลูชันของ DTK ที่ห่อหุ้มด้วยฟังก์ชั่นทุบตีซ้ำ

function renameFilesRecursively () {

  SEARCH_PATH="$1"
  SEARCH="$2"
  REPLACE="$3"

  find ${SEARCH_PATH} -type f -name "*${SEARCH}*" | while read FILENAME ; do
      NEW_FILENAME="$(echo ${FILENAME} | sed -e "s/${SEARCH}/${REPLACE}/g")";
      mv "${FILENAME}" "${NEW_FILENAME}";
  done

}

นี่คือวิธีการใช้งาน:

renameFilesRecursively /home/user/my-files apple orange

0

จริงๆแล้วrenameมีตัวเลือกสำหรับการเรียก--substหรือ-sสั้น ๆ ว่า ไม่จำเป็นต้องใช้ไวยากรณ์ regex

rename -s '#U00a9' 'safe' *

หากคุณต้องการที่จะเปลี่ยน / ทดแทนเกิดขึ้นหลายใช้หรือ--subst-all-S

BTW ฉันแค่ต้องการแทนที่สตริงโดยไม่มีอะไร (ลบออกจากชื่อไฟล์) ... ดีเรายังมีตัวเลือกสำหรับมัน-d/--deleteและ-D/--delete-all:

rename -d '#U00a9' *

-1

อีกทางเลือกหนึ่งคือการใช้งานpyRenamerแอพพลิเคชั่นที่ทำขึ้นเพื่อการเปลี่ยนชื่อแบทช์

มันสามารถติดตั้งได้ด้วย sudo apt-get install pyrenamer

สำหรับรายละเอียดการใช้งานโปรดดูไฟล์ README ของบน GitHub


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