我有一些从 IMAP 服务器下载的目录。
例子:
$ find . -maxdepth 1
.
./&BCEEPwQwBDw-
./&BCMENAQwBDsENQQ9BD0ESwQ1-
./inbox
./&BCcENQRABD0EPgQyBDgEOgQ4-
./&BB4EQgQ,BEAEMAQyBDsENQQ9BD0ESwQ1-
./&BBgEQQRFBD4ENARPBEkEOAQ1-
./Archive
这些是以 UTF-7 编码的西里尔字母名称。据我了解,utf-7编码单元都是有效的Unicode代码点<127,同时也是有效的ASCII。这意味着我可以在任何我想要的地方复制、粘贴、管道和cat它们。
我们来做一下转换:
$ ls | iconv -f utf7 -t utf8
&BB4EQgQ,BEAEMAQyBDsENQQ9BD0ESwQ1-/
&BBgEQQRFBD4ENARPBEkEOAQ1-/
&BCEEPwQwBDw-/
&BCMENAQwBDsENQQ9BD0ESwQ1-/
&BCcENQRABD0EPgQyBDgEOgQ4-/
Archive/
inbox/
瓦?没有效果?iconv -l
列出 utf-7 和 utf-8。
怎么了?
答案1
将西里尔字母从 UTF8 转换为 UTF7 的快速测试
echo 'Here we go. Це коротке речення' | iconv -f utf-8 -t utf-7
Here we go. +BCYENQ +BDoEPgRABD4EQgQ6BDU +BEAENQRHBDUEPQQ9BE8
读一UTF7 的说明编码 我可以看到(粗略地说)每个编码字符串前面必须带有+
.您的 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 代码解决了我的问题:
答案3
有一个 Perl 模块用于在 IMAP 的修改后的 UTF-7 和 UTF-8 或其他编码之间进行解码(或编码):编码::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 系统上至少iconv
支持一种UTF-7-IMAP
编码。ls
尽管换行符不是有效字符,但您无法将其输出提供给它:
$ 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
's重命名这些文件rename
(此处使用的是 File::Rename 2.0.1 中的文件,请注意 's 有多种变体和版本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-, Удаленные)