วิธีเปลี่ยนชื่อไฟล์จำนวนมากด้วยการเข้ารหัสที่ไม่ถูกต้องหรือเปลี่ยนอักขระที่เข้ารหัสไม่ถูกต้องจำนวนมากได้อย่างไร


15

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

./music/Bändname - Some Title - additional Info/B�ndname - 07 - This Title Is Cörtain, The EncÃding Not.mp3

โดยหลักการแล้วฉันต้องการลบทุกอย่างที่ไม่ใช่ตัวอักษรA-Z/ a-zหรือตัวเลข0-9หรือขีด-/ ขีดล่าง_... ผลลัพธ์ควรมีลักษณะดังนี้:

./music/Bndname-SomeTitle-additionalInfo/Bndname-07-ThisTitleIsCrtain,TheEncdingNot.mp3

วิธีการบรรลุนี้สำหรับชุดของไฟล์และไดเรกทอรีจำนวนมาก?

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

แต่นี่เป็นการแก้ไขการเข้ารหัสเท่านั้นฉันต้องการวิธีที่เข้มงวดมากขึ้นตามที่อธิบายไว้ข้างต้น

คำตอบ:


14

คุณจะพบปัญหาบางอย่างหากคุณต้องการเปลี่ยนชื่อไฟล์และไดเรกทอรีในเวลาเดียวกัน การเปลี่ยนชื่อไฟล์เป็นเรื่องง่ายพอ แต่คุณต้องการแน่ใจว่าไดเรกทอรีนั้นถูกเปลี่ยนชื่อด้วย คุณทำไม่ได้mv Motörhead/Encöding Motorhead/Encodingเนื่องจากMotorheadไม่มีอยู่ในเวลาที่โทร

ดังนั้นเราต้องมีการสำรวจเส้นทางในระดับลึกของไฟล์และโฟลเดอร์ทั้งหมดจากนั้นเปลี่ยนชื่อไฟล์หรือโฟลเดอร์ปัจจุบันเท่านั้น การทำงานต่อไปนี้กับ GNU findและ Bash 4.2.42 บน OS X ของฉัน

#!/usr/bin/env bash
find "$1" -depth -print0 | while IFS= read -r -d '' file; do
  d="$( dirname "$file" )"
  f="$( basename "$file" )"
  new="${f//[^a-zA-Z0-9\/\._\-]/}"
  if [ "$f" != "$new" ]      # if equal, name is already clean, so leave alone
  then
    if [ -e "$d/$new" ]
    then
      echo "Notice: \"$new\" and \"$f\" both exist in "$d":"
      ls -ld "$d/$new" "$d/$f"
    else
      echo mv "$file" "$d/$new"      # remove "echo" to actually rename things
    fi
  fi
done

คุณสามารถเปลี่ยน regex โดยใช้new="${f//[\\\/\:\*\?\"<>|]/}"หากคุณต้องการแทนที่สิ่งที่ Windows ไม่สามารถจัดการได้

บันทึกสคริปต์นี้เป็นให้มันปฏิบัติการด้วยrename.sh จากนั้นเรียกมันเหมือนchmod +x rename.shrename.sh /some/path

ตรวจสอบให้แน่ใจว่าได้แก้ไขการชนชื่อไฟล์ (“ Notice” ประกาศ)

หากคุณแน่ใจว่าเป็นการเปลี่ยนที่ถูกต้องให้ลบechoสคริปต์ออกเพื่อเปลี่ยนชื่อสิ่งต่างๆแทนที่จะพิมพ์สิ่งที่ทำ

เพื่อความปลอดภัยฉันขอแนะนำให้ทดสอบสิ่งนี้ในไฟล์ย่อย ๆ ก่อน


ตัวเลือกอธิบาย

เพื่ออธิบายสิ่งที่เกิดขึ้นที่นี่:

  • -depthจะตรวจสอบให้แน่ใจว่าไดเรกทอรีถูกเรียกซ้ำแล้วซ้ำก่อนอื่นดังนั้นเราจึงสามารถ "พับ" ทุกสิ่งตั้งแต่ต้นจนจบ โดยปกติแล้วการfindสำรวจจะแตกต่างกัน (แต่ไม่ใช่ความกว้างก่อน)
  • -print0ทำให้แน่ใจว่าfindเอาต์พุตเป็นตัวคั่นที่ไม่มีค่าดังนั้นเราจึงสามารถอ่านมันread -d ''เข้าไปในfileตัวแปรได้ การทำเช่นนี้ช่วยให้เราจัดการกับชื่อไฟล์แปลก ๆ ทุกประเภทรวมถึงชื่อที่มีช่องว่างและแม้แต่การขึ้นบรรทัดใหม่
  • dirnameเราจะได้รับไดเรกทอรีของแฟ้มที่มี อย่าลืมพูดตัวแปรของคุณให้ถูกต้องเสมอมิฉะนั้นเส้นทางใดก็ตามที่มีช่องว่างหรืออักขระกลมจะทำให้สคริปต์นี้ผิด
  • เราจะได้รับชื่อไฟล์ที่เกิดขึ้นจริง (หรือชื่อ directory) basenameด้วย
  • จากนั้นเราลบอักขระที่ไม่ถูกต้องออกจากการ$fใช้ความสามารถในการแทนที่สตริงของ Bash ไม่ถูกต้องหมายถึงสิ่งใดก็ตามที่ไม่ใช่ตัวอักษรตัวพิมพ์เล็กหรือใหญ่, ตัวเลข, เครื่องหมายทับ ( \/), จุด ( \.), ขีดล่าง, หรือเครื่องหมายขีดกลางลบ
  • ถ้า$fสะอาดแล้ว (ชื่อที่ทำความสะอาดเหมือนกับชื่อปัจจุบัน) ให้ข้ามไป
  • หาก$newมีอยู่แล้วในไดเรกทอรี$d(เช่นคุณมีไฟล์ชื่อresumeและrésuméอยู่ในไดเรกทอรีเดียวกัน) ออกคำเตือน คุณไม่ต้องการเปลี่ยนชื่อเพราะในบางระบบmv foo fooจะทำให้เกิดปัญหา มิฉะนั้น,
  • ในที่สุดเราก็เปลี่ยนชื่อไฟล์ต้นฉบับ (หรือไดเรกทอรี) เป็นชื่อใหม่

ตั้งแต่นี้จะดำเนินการในลำดับชั้นที่ลึกที่สุด, การเปลี่ยนชื่อMotörhead/Encödingเพื่อMotorhead/Encodingที่จะทำในขั้นตอนที่สอง:

  1. mv Motörhead/Encöding Motörhead/Encoding
  2. mv Motörhead Motorhead

สิ่งนี้ทำให้มั่นใจได้ว่าการเปลี่ยนทั้งหมดจะเสร็จสิ้นในลำดับที่ถูกต้อง


ตัวอย่างไฟล์และทดสอบการทำงาน

สมมติว่าไฟล์บางไฟล์ในโฟลเดอร์ฐานเรียกว่าtest:

test
test/Motörhead
test/Motörhead/anöther_file.mp3
test/Motörhead/Encöding
test/Randöm
test/Täst
test/Täst/Töst
test/with space
test/with-hyphen.txt
test/work
test/work/resume
test/work/résumé
test/work/schedule

นี่คือเอาต์พุตจากการรันในโหมดดีบัก (ที่echoด้านหน้าmv) เช่นคำสั่งที่จะถูกเรียกและคำเตือนการชนกัน:

mv test/Motörhead/anöther_file.mp3 test/Motörhead/another_file.mp3
mv test/Motörhead/Encöding test/Motörhead/Encoding
mv test/Motörhead test/Motorhead
mv test/Randöm test/Random
mv test/Täst/Töst test/Täst/Tost
mv test/Täst test/Tast
mv test/with space test/withspace
Notice: "resume" and "résumé" both exist in test/work:
-rw-r—r--  …  …  test/work/resume
-rw-r—r--  …  …  test/work/résumé

ขอให้สังเกตกรณีที่ไม่มีข้อความสำหรับwith-hyphen.txt, scheduleและtestตัวเอง


1
คุณอาจต้องการเพิ่มตรรกะในการจัดการเคสที่มีปลายทางที่mvมีอยู่แล้วซึ่งสามารถเกิดขึ้นได้ (1) หากคุณมีไฟล์ที่สะอาดอยู่แล้ว (เป็นผลลัพธ์mv foo foo) หรือ (2) หากคุณมีไฟล์ที่มีชื่อเดียวกันยกเว้น สำหรับอักขระพิเศษ (เช่นmv Encöding Encodingที่ซึ่งคุณมีEncodingไฟล์เพิ่มเติมอยู่แล้วEncöding)
Scott

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

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

+1 สำหรับการใช้ตัวอย่างกับ "Encöding" มากเกินไปfön! :-)
Marcel

หลังจากสามปีฉันยังคงกลับมาที่นี่ มีประโยชน์มาก ๆ ! :-)
แอฟริกา

15

ฉันรู้ว่ามันไม่ได้เป็นอย่างที่คุณต้องการ แต่ถ้าคุณรู้ว่าการเข้ารหัสดั้งเดิมบางทีคุณสามารถใช้convmvเพื่อเปลี่ยนการเข้ารหัสเป็น UTF-8 ซึ่งควรแก้ไขปัญหาส่วนใหญ่

สิ่งนี้ใช้ได้กับฉันในโฟลเดอร์ที่มีชื่อไฟล์ภาษาโปแลนด์ที่เข้ารหัสไม่ถูกต้อง:

convmv -f cp1250 -t utf8 -r .

โปรดทราบว่าคำสั่งนี้ไม่ได้เปลี่ยนชื่ออะไรเลย เพิ่ม--notestตัวเลือกเพื่อเปลี่ยนชื่อไฟล์จริงๆ


1
สำหรับผู้ที่มีชุดแบบคงที่ (หรือไม่มีชุดอักขระที่หลากหลาย) convmvตัวเลือกนั้นเรียบง่ายและสมบูรณ์แบบอย่างน่าอัศจรรย์ สำหรับ OP มีแนวโน้มที่จะมีตัวอักษรจำนวนมากสิ่งนี้อาจถูกรวมเข้ากับคำตอบอื่น ๆ เนื่องจากconvmvดูเหมือนจะรู้ว่าเมื่อใดหรือเมื่อพบรูปแบบที่ไม่ถูกต้อง โดยการวนลูปผ่าน charsets ผ่านconvmv --listหนึ่งจะได้รับการเข้ารหัสอย่างถูกต้อง

1
ถ้าอย่างนั้นฉันหมายความว่าถ้าในฐานะ OP ทำงานเซิร์ฟเวอร์ Debian ใครจะสันนิษฐาน UTF8 ในทุกวันนี้ซึ่งในกรณีนี้เราสามารถเก็บตัวอักษรดั้งเดิมไว้ได้ ฉันมีโฟลเดอร์ของตัวอักษรนอร์ดิกบางตัวและใช้: convmv -t utf8 --nfc -f iso-8859-1 --notest -r .- --nfcคือเพื่อให้สอดคล้องกับ Linux ล่วงหน้าของ OS X หรือมากกว่านั้นเพียงพิมพ์convmvให้ตัวเลือก (มีประโยชน์)

0

ฉันรู้คุณถามเกี่ยวกับการเปลี่ยนชื่อ

แต่คุณสามารถหลบปัญหาค่อนข้างง่ายโดยใช้ซอฟต์แวร์เช่นMusicBrainz Picard

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

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

(ฉันพูดถึงมันฟรีหรือไม่ทั้งในคำพูดฟรีและในเบียร์ฟรีทั้งซอฟต์แวร์และฐานข้อมูล .. ?)

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