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


20

このファイルのように、特殊文字を含むファイルを含む多数のディレクトリとサブディレクトリがあります。

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

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

robbie@phil:~$ find testsktest.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. オプションで、äなどの特殊文字を音訳する機能(必須ではありませんが、素晴らしいです)

または

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

私はすべてのファイルを繰り返して移動するなどの断片を持っていますが、mvコマンド用にファイルを識別して正しくフォーマットすることは難しい部分のようです。

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


以下の単一の答えは最初の方法に従います(それらを見つけて新しいエンコーディングに名前を変更します)が、2番目の方法も興味深いでしょう:今、リモートファイル名に使用されているエンコーディングを知っているとき、そのようなリモートホストにsshする方法ファイル名が正しく表示される方法(およびキーボードで名前を入力することで管理できます)?
imz-イヴァンザカリヤシェフ

回答:


21

名前に有効な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実際にファイルの名前を変更せずに、何をしているかを示すために渡すことができます。


ありがとう、今日はこれらのことをいくつか試してみます!これが受け入れられる答えになるように見えます:)
RobbieV

見つける| grep '[[:print:]]'コマンドは、単にすべてのファイルを返すようです。UTF-8は、「通常の」文字を使用する他の多くのエンコーディングと互換性がありませんか?
ロビーV

@RobbieV:grep [^[:print:]]印刷できない文字をタイプミスして検索するつもりでした。しかし、私はGNU grepでテストしたばかりであり、無効なUTF-8シーケンスはキャッチされ[^[:print:]]ません(印刷不可能な文字ではなく、文字ではないので理にかなっています)。無効なutf8シーケンスで行をgrepするより長い方法で投稿を編集しました。recodeおよびの方向も修正していることに注意してくださいiconv
ジル 'SO-悪であるのをやめる'

それは完全に機能しました。iconvを除くすべてのコマンドを試してみましたが、すべて正常に機能します。純粋な魔法!
ロビーV

推奨されるlatin1エンコーディングでさえ正しいものでした:)
RobbieV

1

私はこれが古い質問であることを知っていますが、私は一晩中同じような解決策を探しています。いくつかの役立つヒントを見つけましたが、必要なことを正確に実行できなかったので、探していた正しい結果を得るためにいくつかを組み合わせなければなりませんでした

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

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)明確にするために、あなたは変更する場合があります`…`$(…)見る- このこの、およびこれを。(2)"$f"正当な理由がない限り、シェル変数の参照(例:)を常に引用する必要があります。これはにも適用されecho "$f" | sed …ます。また、式全体$(…)(または`…`)にも適用されます。すなわち、mv "$f" "$(echo "$f" | sed "…")"。…(続き)
スコット

(続き)…(3)で始まるファイル名から保護するには、と言う必要があります。(4)「foo♥bar.txt」および「foo♠bar.txt」という名前のファイルがある場合、これは両方を「foo.bar.txt」に名前変更しようとします。破棄するファイル。(5)一体どうしてこれを1分に1回したいのですか?mv -- "$f" …-
スコット

ファイルを自動ダウンロードするトレントスクリプトがあります。また、一部のファイルには、アップローダーをスローする文字が含まれている場合があります。そのため、特殊文字を使用してファイルの名前を変更するだけで、cronがすべての問題を修正し、アップローダーはその仕事をスムーズに行います。
Topps70

そのため(このファイルは、down_loaded.ext)になります(this.fi.le.tha.t.was.down.loaded.ext)
Topps70

0

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

同じように、私は、このように、おそらく、その特別なエンコーディングに働くだろうというローカルターミナルを起動することができます:

LC_ALL = en_US.latin1 xvt&

xvt 端末プログラムの略です。

おそらく、既存のロケールはen_US.iso88591であり、ではなくと呼ばれますen_US.latin1


0

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

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

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