web-dev-qa-db-ja.com

特殊文字を含むファイルの一括名前変更(または正しく表示)

次のような特殊文字を含むファイルを含むディレクトリとサブディレクトリがたくさんあります。

robbie@phil:~$ ls test�sktest.txt 
test?sktest.txt

Findはエスケープシーケンスを明らかにします。

robbie@phil:~$ find test�sktest.txt -ls 
424512 4000 -rwxr--r-x   1 robbie   robbie    4091743 Jan 26 00:34 test\323sktest.txt

コンソールで名前を入力できる唯一の理由は、タブ補完のためです。これは、手動で名前を変更できる(そして特殊文字を削除できる)ことも意味します。

LC_ALLをUTF-8に設定しましたが、これは役に立たないようです(新しいシェルでも同様です)。

robbie@phil:~$ echo $LC_ALL
en_US.UTF-8

Macからsshを使用してマシンに接続しています。これはUbuntuのインストールです。

robbie@phil:~$ cat /etc/lsb-release 
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=7.10
DISTRIB_CODENAME=gutsy
DISTRIB_DESCRIPTION="Ubuntu 7.10"

シェルはBashで、TERMはxterm-colorに設定されています。

これらのファイルはかなり前から存在しており、Ubuntuのインストールを使用して作成されていません。そのため、以前はシステムのエンコーディング設定がどうなっていたのかわかりません。

私は次のことに沿って物事を試しました:

find . -type f -ls | sed 's/[^a-zA-Z0-9]//g'

しかし、私は私が望むすべてを行うソリューションを見つけることができません:

  1. 表示できない文字を含むすべてのファイルを特定します(上記では無視しすぎています)
  2. ディレクトリツリー内のすべてのファイルに対して(再帰的に)、mv oldname newnameを実行します
  3. オプションで、äなどの特殊文字を音訳する機能(必須ではありませんが、すばらしいでしょう)

OR

  1. これらすべてのファイルを正しく表示します(アプリケーションを開こうとしたときにエラーが発生しません)。

すべてのファイルを繰り返し処理して移動するような細かい部分がありますが、ファイルを識別してmvコマンド用に正しくフォーマットするのは難しいようです。

それらが正しく表示されない理由、または正しいエンコーディングを「推測」する方法に関する追加情報も歓迎します。 (私はconvmvを試しましたが、それが私が望んでいることを正確に実行していないようです: http://j3e.de/linux/convmv/

20
RobbieV

名前に有効なUTF-8ではないバイトシーケンスが名前に含まれているため、この無効な文字が表示されると思います。典型的なUNIXファイルシステム(あなたを含む)のファイル名はバイト文字列であり、使用するエンコーディングを決定するのはアプリケーション次第です。今日、UTF-8を使用する傾向がありますが、特にプレーンASCIIで存続できず、UTF-8が存在する前から他のエンコーディングを使用していたロケールでは、普遍的ではありません。

LC_CTYPE=en_US.iso88591 lsを試して、ファイル名がISO-8859-1(latin-1)で意味があるかどうかを確認してください。表示されない場合は、他のロケールを試してください。ここではLC_CTYPEロケール設定のみが重要であることに注意してください。

UTF-8ロケールでは、次のコマンドは、名前が有効なUTF-8ではないすべてのファイルを表示します。

grep-invalid-utf8 () {
  Perl -l -ne '/^([\000-\177]|[\300-\337][\200-\277]|[\340-\357][\200-\277]{2}|[\360-\367][\200-\277]{3}|[\370-\373][\200-\277]{4}|[\374-\375][\200-\277]{5})*$/ or print'
}
find | grep-invalid-utf8

recode または iconv を使用して、それらが別のロケールでより意味があるかどうかを確認できます。

find | grep-invalid-utf8 | recode latin1..utf8
find | grep-invalid-utf8 | iconv -f latin1 -t utf8

一連のファイル名が特定のエンコーディング(例:latin1)であると判断したら、ファイル名を変更する1つの方法は次のとおりです。

find | grep-invalid-utf8 |
rename 'BEGIN {binmode STDIN, ":encoding(latin1)"; use Encode;}
        $_=encode("utf8", $_)'

これは、DebianおよびUbuntuで利用可能なPerl rename コマンドを使用します。これを-nに渡して、実際にファイルの名前を変更することなく、何が行われるかを示すことができます。

私はこれが古い質問であることを知っていますが、私は同様の解決策を一晩中探していました。私はいくつかの役立つヒントを見つけましたが、それらが私が必要とするものを正確に実行しなかったので、私が探していた正しい結果を得るためにいくつかを混ぜて一致させる必要がありました

単に特殊文字を削除し、それらを(。)ドットで置き換える

for f in *.txt; do mv "$f" `echo $f | sed "s/[^a-zA-Z0-9.]/./g"`; done

cronジョブで使用するために、毎分実行するために次のことを行いました

*/1 * * * * cd /path/to/files/ && for f in *.txt; do mv "$f" `echo $f | sed "s/[^a-zA-Z0-9.]/./g"`; done >/dev/null 2>&1

それが私の一日を作ったので、誰かがこれが役に立ったと思います:)

1
Topps70

ここで、リモートエンドのファイル名に使用されているエンコーディングがわかっている場合(「latin1」-最初の回答へのコメントによる)、2番目の方法に従うこともできます-ローカルターミナルとsshリモートファイル名が(ではなく)正しく表示されるように実行します最初の方法:名前を変更します)

me のように、おそらく次のように、その特殊なエンコーディングで動作する端末をローカルで起動できます。

LC_ALL = en_US.latin1 xvt&

xvtは端末プログラムを表します。

おそらく、私が想定したように、既存のロケールはen_US.iso88591ではなくen_US.latin1と呼ばれます。

これは一括要件を満たしていませんが、同じような名前のファイルに複数のバージョンがあり、1つの奇妙な文字のみが異なるという同様の問題が発生しました。残念ながら、これは私が通常使用するワイルドカードトリックを使用して犯罪者の名前を変更できないことを意味しました。

最後に、Filezillaを使用してSFTPクライアントとして接続し、ファイルを参照し、GUIを使用してそれらの名前を変更しました。 Filezillaは危険な文字をかなりうまく処理しました。

0
kabadisha