เปลี่ยนชื่อไฟล์ด้วยคำสั่งหนึ่งบรรทัด


10

ฉันมีไดเรกทอรีนี้และต้องการเปลี่ยนชื่อไฟล์:

===> ls -1 Der-vierte-Weise/
10 - 10 - Erkenntniss.ogg
1 - 01 - Hoffnung.ogg
11 - 11 - Wahrheit.ogg
12 - 12 - Dankbarkeit.ogg
13 - 13 - Kredits.ogg
2 - 02 - Familie.ogg
3 - 03 - Demut.ogg
4 - 04 - Freude.ogg
5 - 05 - Schoenheit.ogg
6 - 06 - Solidaritaet.ogg
7 - 07 - Entscheidung.ogg
8 - 08 - Hilfe.ogg
9 - 09 - Unterstuetzung.ogg

ผลลัพธ์ควรมีลักษณะเช่นนี้:

===> ls -1 Der-vierte-Weise/
01 - Hoffnung.ogg
02 - Familie.ogg
...

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


1
ฉันต้องการแก้ปัญหานี้ด้วยเครื่องมือเชลล์ทั่วไป ฉันไม่ได้บอกว่าคุณไม่มีเหตุผลที่ดี แต่ฉันเชื่อว่าคุณถามและตอบคำถามกับตัวเองว่า "ทำไม" ครั้งสุดท้ายที่ฉันมีปัญหาที่คล้ายกันมากในการแก้ปัญหาฉันผลัก Bash ไปด้านหนึ่งทันทีและแก้ไขมันใน Python ง่ายขึ้นมาก (แต่ฉันรู้จัก Python, วิธีการสตริง, glob.glob และ os.rename แล้ว - และฉันต้องย่อต้นไม้ที่เต็มไปด้วยชื่อเล่นที่มีช่องว่างและอักขระที่น่าอึดอัดใจอื่น ๆ รำคาญถ้าใช้ Python)
nigel222

1
@ nigel222 ฉันขี้เกียจและฉันต้องการพิมพ์ตัวละครให้น้อยที่สุด นั่นเป็นเหตุผลที่ฉันไม่ต้องการใช้หลามที่นี่ อย่าเข้าใจฉันผิด ถึงตอนนี้ Python เป็นภาษาโปรแกรมที่ฉันชอบและใช้ทุกวัน
guettli

คำตอบ:


18

คุณสามารถใช้rename...

rename -n 's/^[0-9]+ - //' *

ลบ-nหลังจากการทดสอบเพื่อเปลี่ยนชื่อไฟล์จริง

คำอธิบาย

  • s/old/new/แทนที่oldด้วยnew
  • ^ จุดเริ่มต้นของสตริง
  • [0-9]+ ตัวเลขบางส่วน

renameเครื่องมือสนับสนุน regex flower ชนิดใด ใช้ PCRE หรือไม่ ... จะดี.
guettli

5
@guettli พูดอย่างเคร่งครัดไม่มันไม่ใช่ PCRE (นั่นคือ Perl ที่เข้ากันได้กับนิพจน์ทั่วไป) renameเป็นสคริปต์ Perl ดังนั้นจึงมีการสนับสนุนอย่างเต็มที่แสดงออก Perl ปกติ; PCRE เป็นเพียงส่วนหนึ่งของสิ่งนั้น แต่สิ่งที่คุณรู้จาก PCRE renameจะใช้บังคับกับ
terdon

@terdon ฉันไม่สนใจการติดตั้ง หากคุณดูด้วยคณิตศาสตร์แก้วแล้วrenameมีการแสดงออกปกติ Perl เข้ากันได้ ใช่การใช้งาน pcre ไม่ได้ถูกนำมาใช้ ฉันเข้าใจสิ่งนี้ :-) ขอบคุณสำหรับคำตอบที่รวดเร็ว
guettli

9

bash การขยายพารามิเตอร์เพื่อตัดส่วนที่ต้องการตั้งแต่เริ่มต้น:

for f in *[[:blank:]]*.ogg; do echo mv -i -- "$f" "${f#[[:digit:]]*-[[:blank:]]}"; done

รูปแบบการขยายตัว:

for f in *[[:blank:]]*.ogg; do 
    echo mv -i -- "$f" "${f#[[:digit:]]*-[[:blank:]]}"
done

echoสำหรับการทำงานแบบแห้ง กำจัดมันสำหรับการกระทำจริง:

for f in *[[:blank:]]*.ogg; do mv -i -- "$f" "${f#[[:digit:]]*-[[:blank:]]}"; done

ตัวอย่าง:

% ls -1
1 - 01 - Hoffnung.ogg
2 - 02 - Familie.ogg

% for f in *[[:blank:]]*.ogg; do mv -i -- "$f" "${f#[[:digit:]]*-[[:blank:]]}"; done 

% ls -1                                                                             
01 - Hoffnung.ogg
02 - Familie.ogg

ใช่แล้ว ขอบคุณ. เนื่องจากฉันรู้ว่าการแสดงออกปกติที่เข้ากันได้ของ Perl จาก Python (ซึ่งฉันใช้ทุกวัน) ฉันชอบrenameคำสั่งมากกว่า (จำเป็นต้องพิมพ์น้อยลง)
guettli

1
@guettli renameเป็นวิธีที่จะไปหากคุณคุ้นเคยกับ PCRE คำตอบที่ได้รับอยู่แล้วเพื่อให้มีการย้ายไปอยู่กับบริสุทธิ์rename bashเพียงแค่ต้องทราบโมดูลpythonของre(หรือregex) ไม่ได้เป็น BTW ที่รองรับ PCRE อย่างสมบูรณ์
heemayl

@guettli คุณเพิ่งลดระดับคำตอบของฉันด้วยหรือไม่ : O
heemayl

ใช่ฉันทำแล้วและฉันก็สนับสนุนความคิดเห็นของคุณ ฉันหวังว่าคุณจะไม่ใช้มันเป็นการส่วนตัว อย่าเข้าใจฉันผิด แต่ความเห็นส่วนตัวของฉันคือสิ่งนี้${f#[[:digit:]]*-[[:blank:]]}น่าเกลียด ใช่มันใช้งานได้ แต่เราอาศัยอยู่ในศตวรรษที่ 21 ฉันคิดว่าถึงเวลาเปลี่ยนจาก "ใช้งานได้" เป็น "ง่ายและสนุก" หาก "มันใช้งานได้" เป็นเป้าหมายแล้ว linux จะไม่ลดอคติที่ไม่เป็นมิตรกับผู้ใช้ เนื่องจากคุณได้รับการโหวตมากแล้วการลงคะแนนเสียงครั้งนี้จึงไม่ควรทำให้เจ็บ (หวังว่า) ถ้าเป็นเช่นนั้นบอกฉันและฉันจะเอามันกลับมา
guettli

1
@guettli อะไรก็ตามที่เหมาะกับคุณ ที่นี่: gnu.org/software/bash/manual/html_node/ ......เพียงเพื่อทราบว่าตัวละครคลาส[[:digit:]]และ[[:blank:]]อยู่ที่นั่นเพื่อให้สอดคล้องกับคุณlocaleเหล่านี้เป็นเรื่องธรรมดาใน Regex เช่นกัน
heemayl
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.