web-dev-qa-db-ja.com

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

私は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

多くのファイルとディレクトリのバッチでこれを達成するにはどうすればよいですか?

私はこの同様の質問を見ました: 特殊文字を含むファイルの一括名前変更(または正しく表示)

しかし、これはエンコーディングを修正するだけなので、上記のように、より厳密なアプローチを好みます。

16
Afr

ファイルのディレクトリの名前を同時に変更したい場合、いくつかの問題が発生します。ファイルの名前を変更するのは簡単です。ただし、ディレクトリの名前も変更する必要があります。 Motorheadは呼び出し時に存在しないため、単純にmv Motörhead/EncöDing Motorhead/Encodingすることはできません。

したがって、すべてのファイルとフォルダーの縦型検索を行ってから、現在のファイルまたはフォルダーのみの名前を変更する必要があります。以下は、OS XのGNU findおよび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

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

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

ファイル名の競合をすべて解決してください(「Notice」アナウンス)。

絶対に確実が正しい置換を行う場合は、スクリプトからechoを削除して、実際の名前を変更するだけでなく、実際の名前を変更します。

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


オプションの説明

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

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

これは最も深い階層でのみ機能するため、Motörhead/EncöDingからMotorhead/Encodingへの名前変更は2つのステップで行われます。

  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.txtschedule、およびtest自体のメッセージがないことに注意してください。

14
slhck

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

これは、無効にエンコードされたポーランド語ファイル名がいくつかあるフォルダーで私にとってはうまくいきました:

convmv -f cp1250 -t utf8 -r .

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

15
mik01aj

私は知っています、あなたは名前の変更について尋ねました。

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

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

このアプローチでは、ファイルが読み取り可能で完全なものである限り、コレクションの名前がどれほど厄介で悪意のあるものであるかは問題ではありません。

(私はそれが無料だと言いましたか?言論の自由とビールの両方のように?ソフトウェアとデータベースの両方..?)

0
Alois Mahdal