IMAPサーバーから取得したutf7ファイル名を正しくデコードする方法

IMAPサーバーから取得したutf7ファイル名を正しくデコードする方法

IMAPサーバーからいくつかのディレクトリをダウンロードしました。

例:

$ find . -maxdepth 1
.
./&BCEEPwQwBDw-
./&BCMENAQwBDsENQQ9BD0ESwQ1-
./inbox
./&BCcENQRABD0EPgQyBDgEOgQ4-
./&BB4EQgQ,BEAEMAQyBDsENQQ9BD0ESwQ1-
./&BBgEQQRFBD4ENARPBEkEOAQ1-
./Archive

これはUTF-7でエンコードされたキリル文字の名前です。私が知る限り、UTF-7エンコーディング単位はすべて127未満の有効なUnicodeコードポイントであり、有効なASCIIでもあります。つまり、好きな場所にコピー、貼り付け、パイプ、猫を表示できます。

変換してみましょう:

$ ls | iconv -f utf7 -t utf8
&BB4EQgQ,BEAEMAQyBDsENQQ9BD0ESwQ1-/
&BBgEQQRFBD4ENARPBEkEOAQ1-/
&BCEEPwQwBDw-/
&BCMENAQwBDsENQQ9BD0ESwQ1-/
&BCcENQRABD0EPgQyBDgEOgQ4-/
Archive/
inbox/

ワット?効果がないですか?iconv -lutf-7とutf-8をリストします。

何が問題なの?

答え1

キリル文字をUTF8からUTF7に変換するクイックテスト

echo 'Here we go. Це коротке речення' | iconv -f utf-8 -t utf-7
Here we go. +BCYENQ +BDoEPgRABD4EQgQ6BDU +BEAENQRHBDUEPQQ9BE8

一つ読んでくださいUTF7の説明+Encoding UTF7ディレクトリリストには、各エンコーディング文字列の前にある必要があることを(おおよそ言うと)知ることができます。

ご覧のように、抽出されたデータを次に変換しても有効なコードポイントは生成されません&+

echo '&BB4EQgQ,BEAEMAQyBDsENQQ9BD0ESwQ1-/' | tr '&' + | iconv -f utf-7 -t utf-8
От
iconv: (stdin):1:2: cannot convert

&ただし、ファイル名自体を使用している場合に切り替えると、有効な変換が得られます+

echo '&BCMENAQwBDsENQQ9BD0ESwQ1-' | tr '&' + | iconv -f utf-7 -t utf-8
Удаленные

答え2

本質的に、この質問は不適切です。問題は、IMAP(ab)がutf-7を使用していることです。ほとんどUTF-7ですが、正確ではありません。最後に、PHPドキュメントコメントのPHPコードを使用して問題を解決しました。

imap-utf7のPHPドキュメント

答え3

IMAPの修正されたUTF-7とUTF-8または他のエンコーディングの間にデコード(またはエンコーディング)用のPerlモジュールがあります。エンコーディング::IMAPUTF7。したがって、コマンドラインから直接デコードするのは非常に簡単です。

通常、デフォルトではインストールされません。 Debianベースのシステム(Ubuntuなど)にインストールするには:

sudo apt install libencode-imaputf7-perl

またはMacOSでは:

cpanp i Encode::IMAPUTF7

Bash端末の現在のディレクトリにあるすべてのファイルまたはフォルダの名前をUTF-8に変更する一行の例:

find . -depth -name '*&*' | while read x; do new=$(perl -CSA -MEncode::IMAPUTF7 -le 'print Encode::IMAPUTF7::decode(\"IMAP-UTF-7\", shift)' "$x") && mv -v "$x" "$new"; done

または、読みやすくするために、より多くの行に分割します。

find . -depth -name '*&*' \
| while read x; do
    new=$(perl -CSA -MEncode::IMAPUTF7 -le 'print Encode::IMAPUTF7::decode(\"IMAP-UTF-7\", shift)' "$x") \
      && mv -v "$x" "$new";
  done

答え4

最近のGNUシステムでは、少なくともiconv1つのエンコーディングがサポートされていますUTF-7-IMAPls改行文字は有効な文字ではありませんが、出力を渡すことはできません。

$ ls | iconv -f UTF-7-IMAP
Archiveiconv: illegal input sequence at position 7

使用すると、-cデコードできない文字は無視されます。

$ ls | iconv -cf UTF-7-IMAP
ArchiveОтправленныеИсходящиеЧерновикиСпамУдаленныеinbox

または、各ファイル名を個別に指定できますiconv

$ for f in *; do printf %s "$f" | iconv -f UTF-7-IMAP; echo; done
Archive
Отправленные
Исходящие
Черновики
Спам
Удаленные
inbox

または、次の操作を行います。

$ printf '%s&AAo-' * | iconv -f UTF-7-IMAP
Archive
Отправленные
Исходящие
Черновики
Спам
Удаленные
inbox

&AAo-改行のUTF-7-IMAPエンコーディングはどこにありますか?

ほとんどのプログラミング言語にはiconv(3)標準インターフェイスへのバインディングがあります。たとえば、次のようになりますperl

$ perl -MText::Iconv -le '$c = Text::Iconv->new(qw(UTF-7-IMAP UTF-8));
                          print $c->convert($_) for @ARGV' -- *
Archive
Отправленные
Исходящие
Черновики
Спам
Удаленные
inbox

したがって、perl次のようにこれらのファイルの名前を変更できますrename(私は2.0.1でFile :: Renameを使用しています。さまざまなバリエーションとバージョンがあることに注意してくださいrename)。

$ rename -n -- '
    use Text::Iconv;
    our $c //= Text::Iconv->new(qw(UTF-7-IMAP UTF-8));
    $_ = $c->convert($_)' *
rename(&BB4EQgQ,BEAEMAQyBDsENQQ9BD0ESwQ1-, Отправленные)
rename(&BBgEQQRFBD4ENARPBEkEOAQ1-, Исходящие)
rename(&BCcENQRABD0EPgQyBDgEOgQ4-, Черновики)
rename(&BCEEPwQwBDw-, Спам)
rename(&BCMENAQwBDsENQQ9BD0ESwQ1-, Удаленные)

関連情報