無効なエンコードを使用してファイルの名前を一括変更するか、無効なエンコードされた文字を一括置換する方法


15

私はdebianサーバーを持ち、インターネットラジオステーションの音楽をホストしています。多くのファイルが無効なエンコーディングを取得したため、ファイル名とパスに問題があります。たとえば:

./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呼び出しの時点で存在しません。

そのため、すべてのファイルとフォルダーの深さ優先走査を必要とし、現在のファイルまたはフォルダーのみを名前変更します。以下findは、私のOS X上のGNU およびBash 4.2.42で動作します。

#!/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

new="${f//[\\\/\:\*\?\"<>|]/}"Windowsで処理できないものを置き換える場合は、を使用して正規表現を変更できます。

このスクリプトをとして保存しrename.sh、で実行可能にしchmod +x rename.shます。次に、のように呼び出しますrename.sh /some/path

ファイル名の衝突(“ Notice”アナウンス)を必ず解決してください。

あなたがいるなら絶対に確認してくださいそれは右の置換を行い、削除echo、実際にそれが何を印刷するのではなく、物事の名前を変更するスクリプトから。

安全のために、まずファイルの小さなサブセットでこれをテストすることをお勧めします。


オプションの説明

ここで何が起こるかを説明するには:

  • -depthディレクトリが深さ優先で再帰されるようにするため、最後からすべてを「ロールアップ」できます。通常、findトラバースは異なります(ただし、幅優先ではありません)。
  • -print0確実にfind我々がそれを読むことができるように、出力は、ヌルで区切られているread -d ''file変数。そうすることで、スペースや改行を含む、あらゆる種類の奇妙なファイル名に対処できます。
  • でファイルのディレクトリを取得しますdirname。変数を常に適切に引用することを忘れないでください。そうしないと、スペースまたはグロブ文字を含むパスがこのスクリプトを破壊します。
  • で実際のファイル名(またはディレクトリ名)を取得しますbasename
  • 次に、$fBashの文字列置換機能の使用から無効な文字を削除します。無効とは、小文字、大文字、数字、スラッシュ(\/)、ドット(\.)、アンダースコア、マイナスハイフン以外のものを意味します。
  • $f既にクリーンな場合(クリーンな名前は現在の名前と同じです)、スキップします。
  • $newディレクトリに既に存在する場合$d(例えば、あなたが名前のファイルを持っているresumeし、résumé同じディレクトリに)、警告を発行します。一部のシステムでmv foo fooは問題が発生するため、名前を変更したくありません。さもないと、
  • 最後に、元のファイル(またはディレクトリ)の名前を新しい名前に変更します

これが唯一の最も深い階層に作用しますので、名前を変更するMotörhead/EncödingにはMotorhead/Encoding2つの段階で行われます。

  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

デバッグモードでの実行(のechomv)からの出力、つまり呼び出されるコマンドと衝突警告は次のとおりです。

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.txtscheduletest自分自身。


1
mv(1)既にクリーンなファイルがある場合(結果としてmv foo foo)、または(2)を除く同じ名前のファイルがある場合に発生する可能性がある、既に存在する宛先のケースを処理するロジックを追加することができます特殊文字(たとえば、に加えてmv Encöding Encoding既にEncodingファイルがある場合Encöding)。
スコット

良いアイデア、ありがとう。その場合の対処方法に関する具体的な提案はありますか?確かに–これをクリーンで健全な方法で達成することは、最初に思われるよりも難しい。何かあれば、もちろん編集してください。
slhck

衝突を自動的に処理することを考えるのは理にかなっていないと思います。ユーザーにそれらを識別させ、処理させるだけです。あなたの提案通り、私はあなたの答えを編集しました。
スコット

「Encöding」を使用した例の+1 Too muchfön!:-)
マルセル14年

3年後、私はまだここに戻ってきました。とても便利です!:-)
AFR

15

私はそれがあなたが望むものではないことを知っていますが、元のエンコーディングを知っていれば、おそらくconvmvエンコーディングをUTF-8に変更して、ほとんどの問題を修正することができます。

これは、いくつかの無効にエンコードされたポーランド語のファイル名を持つフォルダーで機能しました:

convmv -f cp1250 -t utf8 -r .

このコマンドは実際には何も名前を変更しないことに注意してください。--notest実際にファイルの名前を変更するオプションを追加します。


1
静的セットを持っている人(または文字セットの多様な組み合わせを持たない人)にとって、このconvmvオプションは驚くほどシンプルで完璧です。潜在的な多数の文字セットを持つOPの場合、これは他の回答とマージされる可能性がありconvmvます。それは、いつ、またはいつ正しい形式に遭遇しないかを知っているようだからです。を介して文字セットをループすることにより、convmv --list適切にエンコードされます。

1
これにより、OPとしてDebianサーバーを実行している場合、最近は確かにUTF8を想定していることになります。その場合、元の文字を保持できます。私はいくつかの北欧文字のフォルダを持っていた、と使用:convmv -t utf8 --nfc -f iso-8859-1 --notest -r .- --nfcLinuxの先のOS Xまたはそう、単にタイピングに準拠するようにしたconvmv(便利な)オプションを提供します。

0

名前の変更について尋ねたのは知っています。

しかし、MusicBrainz Picardのようなソフトウェアを使用すると、非常に簡単に問題を回避できます。

音楽を識別し(オーディオフィンガープリント)、巨大なMusicBrainzデータベースからすべての必要なデータ(利用可能な場合はカバーイメージを含む)をダウンロードし、コレクションが好きなパターンに合うようにファイルを移動できます。私は何年も使用していますが、キリル語からアラビア語まで何でも完璧に機能しました。そしてもちろん(少なくともラテン語ベースのスクリプトの場合)、ASCIIへの変換も実行できます。

このアプローチでは、ファイルが読み取り可能で完全である限り、コレクションが実際にどれほど乱雑/不適切な名前であるかは問題ではありません。

(無料だと言いましたか?言論の自由とビールの自由の両方ですか?ソフトウェアとデータベースの両方..?)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.