เปลี่ยนชื่อเป็นจำนวนมาก * รุ่น nix


11

ฉันกำลังมองหาวิธีที่จะเปลี่ยนชื่อไฟล์ที่มีชื่อคล้ายกันจำนวนมากคล้ายกับคำถามนี้ (คำถามที่เกี่ยวข้องกับ Windows)ยกเว้นว่าฉันใช้ * nix (Ubuntu และ FreeBSD แยกกัน) เพียงเพื่อสรุปในขณะที่ใช้เชลล์ (Bash, CSH, ฯลฯ ) ฉันจะเปลี่ยนชื่อไฟล์เป็นจำนวนมากได้อย่างไรเช่นไฟล์ต่อไปนี้:

Beethoven - Fur
Elise.mp3 Beethoven - Moonlight Sonata.mp3
Beethoven - Ode to Joy.mp3
Beethoven - Rage Over the Lost Penny.mp3

จะถูกเปลี่ยนชื่อเป็นเช่นนี้หรือไม่

Fur
Elise.mp3 Moonlight Sonata.mp3
Ode to Joy.mp3
Rage Over the Lost Penny.mp3

เหตุผลที่ฉันต้องการทำเช่นนี้คือการรวบรวมไฟล์เหล่านี้จะอยู่ภายใต้ไดเรกทอรีที่ชื่อ "Beethoven" (เช่นคำนำหน้าชื่อไฟล์) และการมีข้อมูลนี้ในชื่อไฟล์จะซ้ำซ้อน

คำตอบ:


12

ยูทิลิตี้การเปลี่ยนชื่อจะทำสิ่งที่คุณต้องการ

เพียงแค่ใช้ rename 's/Beethoven\ -\ //g' *.mp3


คุณสามารถแก้ไขเพื่อให้ลิงค์ไปยังยูทิลิตี้หรือเป็นมาตรฐานทั้งในการแจกแจงที่กล่าวถึง (Ubuntu และ FreeBSD)?
Chris W. Rea

1
มันมาพร้อมกับ Perl Debian ใช้มันเป็นคำสั่งเปลี่ยนชื่อดังนั้นฉันสงสัยว่า Ubuntu ก็ทำเช่นกัน มีคำสั่ง 'เปลี่ยนชื่อ' อื่นที่ไม่มีค่าควรตรวจสอบ man page
Derobert

ว้าววากยสัมพันธ์ไวยากรณ์เปลี่ยนชื่อมีลักษณะเหมือนกันมากที่จะเป็นกลุ่มแทน: D
Dzung Nguyen

พอร์ตใน / usr / ports / sysutils / เปลี่ยนชื่อทำงานได้อย่างสมบูรณ์แบบใน FreeBSD
Josh W.

10

ชอบหลายสิ่งหลายอย่างกับ Linux / Unix มีมากกว่าหนึ่งวิธีที่จะทำ!

บางคนอาจใช้mmv (มวล mv)

คำสั่งเปลี่ยนชื่อหรือคำสั่ง prename ที่มาพร้อมกับแพ็กเกจ Perl (Ubuntu และเดเบียนที่ใหม่กว่า) สามารถทำได้เช่นกัน

prename 's/Beethoven\ -\ //g' Beethoven*.mp3

โปรดทราบว่าเครื่องมือเปลี่ยนชื่อใน Fedora 10 ไม่ใช่โปรแกรมเดียวกับที่ใช้และทำงานแตกต่างกัน มันเป็นส่วนหนึ่งของแพคเกจที่แตกต่างกัน util ลินุกซ์-ng และสามารถพบได้ที่นี่

ฉันมักจะไปที่เปลือกเพื่อออกจากนิสัย (หลังจากเครื่องมือดังกล่าวไม่ได้อยู่เสมอ)

mkdir -p Beethoven
for x in Beethoven\ -\ *
do
mv "$x" Beethoven/"${x/Beethoven - /}"
done

สิ่งนี้จะสร้างไดเรกทอรี Beethoven จากนั้นย้ายไฟล์ไปยังไดเรกทอรี / ชื่อไฟล์โดยที่ชื่อไฟล์นั้นมีชื่อ "Beethoven -" ถูกแทนที่โดยไม่มีอะไร

เป็นการทดสอบก่อน:

$ ls
Beethoven - Fur Elise.mp3                 Beethoven - Ode to Joy.mp3
Beethoven - Moonlight Sonata.mp3          Beethoven - Rage Over the Lost Penny.mp3

หลังจาก:

$ ls Beethoven/
Fur Elise.mp3                 Ode to Joy.mp3
Moonlight Sonata.mp3          Rage Over the Lost Penny.mp3

4

ลองใช้วิธีแก้ไขปัญหานี้โดยใช้การรวมกันของ grep และเปลี่ยนชื่อ นี่คือการสมมติว่าคุณมีไดเรกทอรีทั้งหมดที่คุณต้องเปลี่ยนชื่อ หากมีเพียงไม่กี่ฉันจะไปด้วยวิธีการด้วยตนเองด้วยรูปแบบ "ศิลปิน -" hardcoded สำหรับแต่ละคน

# Rename any mp3 files in the directory hierarchy of type "a - b.mp3" to "b.mp3"
find . -name "*.mp3" -exec rename -n -v 's|^(.*/).*-\s*(.*)\s*$|$1$2|g' {} \;

ชี้แจงผลการค้นหา : หาคำสั่งพบไฟล์ทั้งหมดที่มี.mp3ขยายในลำดับชั้นของไฟล์ปัจจุบันและเรียกอาร์กิวเมนต์ส่งผ่านไปยัง-execสำหรับแต่ละ โปรดทราบว่าภายใน-exec , {}หมายถึงอาร์กิวเมนต์ที่ส่งผ่านโดยfind (พา ธ ไฟล์ + ชื่อ) มั่นใจได้รับการส่งผ่านไปยังเปลี่ยนชื่อและแทนที่จะแสดงให้เห็นจุดสิ้นสุดของการค้นหาคำสั่ง
\;;

คำสั่งที่ระบุด้านบนมีสวิตช์-n (ไม่มีการดำเนินการ) ดังนั้นมันจะบอกคุณว่าจะเกิดอะไรขึ้นถ้าคุณวิ่ง ฉันแนะนำให้คุณรันคำสั่งนี้โดยไม่ใช้ -n switch หลังจากคุณรันครั้งเดียวและพอใจกับผลลัพธ์ที่เสนอ

ตอนนี้สำหรับ regexp

  • ^ ตรงกับจุดเริ่มต้นของสตริง
  • $ ตรงกับจุดสิ้นสุดของสตริง
  • . ตรงกับตัวละครใด ๆ
  • *หมายถึงศูนย์หรือมากกว่าของการสร้างนำหน้า เช่น.*หมายถึงศูนย์หรือมากกว่าตัวอักษร
  • \s ย่อมาจากอักขระช่องว่างใด ๆ
  • \S ย่อมาจากอักขระที่ไม่ใช่ช่องว่าง
  • สิ่งที่อยู่ภายใน()ได้รับการจับและสะท้อนให้เห็นเป็น$1, $2ขึ้นอยู่กับตำแหน่งของตน

regexp:

  • ค้นหาโครงสร้างไดเรกทอรีทางเลือกเมื่อเริ่มต้นรวบรวมสิ่งนี้ใน $ 1: (.*/)
  • ข้ามทุกอย่างจนถึง " -":.*-
  • จับส่วนที่เหลือของสตริงยกเว้นช่องว่างนำหน้าและต่อท้ายใน $ 2: (.*)
  • เขียนไฟล์เป็น $ 1 $ 2 ซึ่งควรเป็น "/path/to/file/""filename.mp3"

นี่คือการทดสอบการทำงานของฉัน:

/tmp/test$ ls -R
.:
a  b  c  z-unknown.mp3

./a:
a3.mp3                 a - longer title3.mp3  c.mp3   disc2
a - longer title2.mp3  a - long title.mp3     disc 1  the band - the title.mp3

./a/disc 1:
a - title1.mp3  a - title2.mp3

./a/disc2:
a - title1.mp3  a - title2.mp3

./b:
cd - ab - title3.mp3  cd - title1.mp3  cd - title2.mp3  c.mp3

./c:
c-pony2.mp4  c - pony3.mp3  c - pony4.mp3  c-pony.mp3

/tmp/test$ find . -name "*.mp3" -exec rename -v 's|^(.*/).*-\s*(.*)\s*$|$1$2|g' {} \;
./c/c-pony.mp3 renamed as ./c/pony.mp3
./c/c - pony4.mp3 renamed as ./c/pony4.mp3
./c/c - pony3.mp3 renamed as ./c/pony3.mp3
./z-unknown.mp3 renamed as ./unknown.mp3
./a/the band - the title.mp3 renamed as ./a/the title.mp3
./a/a - longer title2.mp3 renamed as ./a/longer title2.mp3
./a/a - longer title3.mp3 renamed as ./a/longer title3.mp3
./a/disc 1/a - title1.mp3 renamed as ./a/disc 1/title1.mp3
./a/disc 1/a - title2.mp3 renamed as ./a/disc 1/title2.mp3
./a/a - long title.mp3 renamed as ./a/long title.mp3
./a/disc2/a - title1.mp3 renamed as ./a/disc2/title1.mp3
./a/disc2/a - title2.mp3 renamed as ./a/disc2/title2.mp3
./b/cd - title1.mp3 renamed as ./b/title1.mp3
./b/cd - title2.mp3 renamed as ./b/title2.mp3
./b/cd - ab - title3.mp3 renamed as ./b/title3.mp3

/tmp/test$ ls -R
.:
a  b  c  unknown.mp3

./a:
a3.mp3  c.mp3  disc 1  disc2  longer title2.mp3  longer title3.mp3  long title.mp3  the title.mp3

./a/disc 1:
title1.mp3  title2.mp3

./a/disc2:
title1.mp3  title2.mp3

./b:
c.mp3  title1.mp3  title2.mp3  title3.mp3

./c:
c-pony2.mp4  pony3.mp3  pony4.mp3  pony.mp3

Regexp เป็นธุรกิจที่ยุ่งยากและฉันได้เขียนความผิดพลาดมากมายดังนั้นฉันจึงยินดีต้อนรับทุก ๆ คนเกี่ยวกับการขาดบุญคุณ ฉันรู้ว่าฉันพบการทดสอบนี้ค่อนข้างน้อย


1

ฉันได้รวบรวมโปรแกรม Java บรรทัดคำสั่งที่ทำให้การเปลี่ยนชื่อไฟล์ (และไดเรกทอรี) เป็นเรื่องง่ายโดยเฉพาะการเขียนสคริปต์ ฟรีและโอเพ่นซอร์สดังนั้นคุณสามารถปรับเปลี่ยนให้เป็นเนื้อหาในหัวใจของคุณ:

RenameWand
http://renamewand.sourceforge.net/

ตัวอย่างการใช้งานที่เกี่ยวข้อง:

ย้ายไฟล์ของแบบฟอร์ม"<a> - <b>"ไปยังไดเรกทอรีที่เกี่ยวข้อง"<a>":

java -jar RenameWand.jar  "<a> - <b>"  "<a>/<b>"

จัดเรียงไฟล์ตามเวลาที่แก้ไขล่าสุดและเปลี่ยนชื่อไฟล์ด้วยตัวเลข 3 หลัก:

java -jar RenameWand.jar  "<a>"  "<3|#FT> <a>"

จัดเรียงส่วนของชื่อไฟล์ใหม่และเปลี่ยนกรณี:

java -jar RenameWand.jar  "<album> - <artist> - <song>.<ext>" 
                          "<artist.upper> <album.title> - <song>.<ext.lower>"


0

สำหรับหัวนกเพนกวินสิ่งนี้ทำได้ง่ายในเชลล์สคริปต์หรือสคริปต์ AWK สำหรับมนุษย์ปุถุชนคุณอาจต้องการทดลองใช้ Midnight Commander มันอยู่ในการแจกแจงลินุกซ์ส่วนใหญ่จาก shell prompt type mc -a คุณสามารถเปลี่ยนชื่อไฟล์โดยใช้นิพจน์ทั่วไป ฉันใช้บทความที่ GeekStuff http://www.thegeekstuff.com/2009/06/how-to-rename-files-in-group/เพื่อช่วยฉัน


0

นี่คือตัวอย่างบรรทัดคำสั่งง่ายๆ ฉันมีคำว่า "สีขาว" อยู่ตรงกลางชื่อของไฟล์ png จำนวนมาก ฉันต้องการที่จะนำมันออกมาและปล่อยให้ขีดเส้นใต้เดียว นี่เป็นการหลอกลวง:

for i in *.png; do mv "$i" "${i/white/}"; done

0

ใช้vidirจากนั้นใช้คุณสมบัติตัวแก้ไขของคุณเพื่อใช้รูปแบบการเปลี่ยนชื่อ

ชื่อ

vidir - แก้ไขไดเรกทอรี

สรุป

vidir [- verbose] [ไดเรกทอรี | ไฟล์ | -] ...

รายละเอียด

vidir อนุญาตให้แก้ไขเนื้อหาของไดเรกทอรีในโปรแกรมแก้ไขข้อความ หากไม่มีการระบุไดเร็กทอรีไดเร็กทอรีปัจจุบันจะถูกแก้ไข

เมื่อแก้ไขไดเรกทอรีแต่ละรายการในไดเรกทอรีจะปรากฏในบรรทัดหมายเลขของตนเอง ตัวเลขเหล่านี้เป็นวิธีที่ vidir ติดตามว่ามีการเปลี่ยนแปลงรายการใดบ้าง ลบบรรทัดเพื่อลบไฟล์ออกจากไดเรกทอรีหรือแก้ไขชื่อไฟล์เพื่อเปลี่ยนชื่อไฟล์ นอกจากนี้คุณยังสามารถสลับหมายเลขคู่เพื่อสลับชื่อไฟล์ได้

โปรดทราบว่าหากระบุ "-" เป็นไดเรกทอรีที่จะแก้ไขมันจะอ่านรายชื่อไฟล์จาก stdin และแสดงไฟล์เหล่านั้นเพื่อทำการแก้ไข หรือสามารถระบุรายการไฟล์ได้ในบรรทัดคำสั่ง

ตัวอย่าง

vidir vidir * .jpeg การใช้งานทั่วไป

ค้นหา | vidir - แก้ไขเนื้อหาไดเรกทอรีย่อยด้วย หากต้องการลบไดเรกทอรีย่อยให้ลบเนื้อหาทั้งหมดและไดเรกทอรีย่อยในเครื่องมือแก้ไข

ค้นหาประเภท f | vidir - แก้ไขไฟล์ทั้งหมดภายใต้ไดเรกทอรีและไดเรกทอรีย่อยปัจจุบัน

ผู้แต่ง

Joey Hess 2006-2010

การดัดแปลงโดย Magnus Woldrich 2011

ลิขสิทธิ์

ลิขสิทธิ์ 2006-2011 vidir "AUTHOR" ตามที่ระบุไว้ข้างต้น

ได้รับใบอนุญาตภายใต้ GNU GPL


0

ใน * ระวังไม่มี perl renameใช้ได้

ใน * ระวังไม่มีการเปลี่ยนชื่อจึงจำเป็นต้องทำการเปลี่ยนชื่อโดยใช้วิธีอื่น ไม่กี่ปีที่ผ่านมาฉันแนะนำzmvที่นี่ซึ่งในขณะที่ยอดเยี่ยมไม่จำเป็นต้องมีเช่นกัน

การใช้ builtins และ sed เราสามารถทำให้เชลล์สคริปต์ทำงานได้อย่างรวดเร็วซึ่งทำให้ไวยากรณ์คล้ายกับสคริปต์เปลี่ยนชื่อ perl ในขณะที่ไม่มีข้อผิดพลาดในการจัดการกับความดีจึงทำให้งานเสร็จสมบูรณ์

sedrename() {
  if [ $# -gt 1 ]; then
    sed_pattern=$1
    shift
    for file in $(ls $@); do
      mv -v "$file" "$(sed $sed_pattern <<< $file)"
    done
  else
    echo "usage: $0 sed_pattern files..."
  fi
}

การใช้

sedrename 's/Beethoven\ -\ //g' *.mp3

before:

./Beethoven - Fur Elise.mp3
./Beethoven - Moonlight Sonata.mp3
./Beethoven - Ode to Joy.mp3
./Beethoven - Rage Over the Lost Penny.mp3

after:

./Fur Elise.mp3
./Moonlight Sonata.mp3
./Ode to Joy.mp3
./Rage Over the Lost Penny.mp3

สมมติว่าเราต้องการสร้างโฟลเดอร์เป้าหมายด้วย ...

เนื่องจากmvไม่ได้สร้างโฟลเดอร์ที่เราไม่สามารถใช้งานได้sedrenameเหมือนที่นี่ แต่เป็นการเปลี่ยนแปลงเล็กน้อยพอสมควรดังนั้นฉันคิดว่ามันดีที่จะรวมไว้ด้วย

เราต้องการฟังก์ชั่นยูทิลิตี้abspath(หรือพา ธ สัมบูรณ์) เพื่อให้เราสามารถสร้างโฟลเดอร์เป้าหมายสำหรับรูปแบบ sed / เปลี่ยนชื่อซึ่งรวมถึงโครงสร้างโฟลเดอร์ใหม่

abspath () { case "$1" in
               /*)printf "%s\n" "$1";;
               *)printf "%s\n" "$PWD/$1";;
             esac; }

เพื่อให้มั่นใจว่าเราทราบชื่อของโฟลเดอร์เป้าหมายของเรา เมื่อเราเปลี่ยนชื่อเราจะต้องใช้มันในชื่อไฟล์เป้าหมาย

# generate the rename target
target="$(sed $sed_pattern <<< $file)"

# Use absolute path of the rename target to make target folder structure
mkdir -p "$(dirname $(abspath $target))"

# finally move the file to the target name/folders
mv -v "$file" "$target"

นี่คือสคริปต์การรับรู้โฟลเดอร์แบบเต็ม ...

sedrename() {
  if [ $# -gt 1 ]; then
    sed_pattern=$1
    shift
    for file in $(ls $@); do
      target="$(sed $sed_pattern <<< $file)"
      mkdir -p "$(dirname $(abspath $target))"
      mv -v "$file" "$target"
    done
  else
    echo "usage: $0 sed_pattern files..."
  fi
}

แน่นอนว่ามันยังใช้งานได้เมื่อเราไม่มีโฟลเดอร์เป้าหมายที่เฉพาะเจาะจงเช่นกัน

หากเราต้องการใส่เพลงทั้งหมดลงในโฟลเดอร์./Beethoven/เราสามารถทำได้ดังนี้:

การใช้

sedrename 's|Beethoven - |Beethoven/|g' *.mp3

before:

./Beethoven - Fur Elise.mp3
./Beethoven - Moonlight Sonata.mp3
./Beethoven - Ode to Joy.mp3
./Beethoven - Rage Over the Lost Penny.mp3

after:

./Beethoven/Fur Elise.mp3
./Beethoven/Moonlight Sonata.mp3
./Beethoven/Ode to Joy.mp3
./Beethoven/Rage Over the Lost Penny.mp3

รอบโบนัส ...

การใช้สคริปต์นี้เพื่อย้ายไฟล์จากโฟลเดอร์ไปยังโฟลเดอร์เดียว:

สมมติว่าเราต้องการรวบรวมไฟล์ทั้งหมดที่จับคู่และวางไว้ในโฟลเดอร์ปัจจุบันเราสามารถทำได้:

sedrename 's|.*/||' **/*.mp3

before:

./Beethoven/Fur Elise.mp3
./Beethoven/Moonlight Sonata.mp3
./Beethoven/Ode to Joy.mp3
./Beethoven/Rage Over the Lost Penny.mp3

after:

./Beethoven/ # (now empty)
./Fur Elise.mp3
./Moonlight Sonata.mp3
./Ode to Joy.mp3
./Rage Over the Lost Penny.mp3

หมายเหตุเกี่ยวกับรูปแบบ sed regex

กฎรูปแบบ sed ทั่วไปที่ใช้ในสคริปต์นี้รูปแบบเหล่านี้ไม่ใช่ PCRE (นิพจน์ปกติที่เข้ากันได้กับ Perl) คุณสามารถเพิ่มไวยากรณ์นิพจน์ปกติได้โดยใช้อย่างใดอย่างหนึ่งsed -rหรือsed -E ขึ้นอยู่กับแพลตฟอร์มของคุณ

ดู POSIX compliant man re_formatสำหรับคำอธิบายที่สมบูรณ์เกี่ยวกับรูปแบบพื้นฐานและแบบขยาย regexp

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