![如何使用命令行解码文件名?](https://linux22.com/image/107741/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8%E5%91%BD%E4%BB%A4%E8%A1%8C%E8%A7%A3%E7%A0%81%E6%96%87%E4%BB%B6%E5%90%8D%EF%BC%9F.png)
是否可以通过命令行解码文件名?
假设我有以下两个文件:
- foo.mp3
- 酒吧.mp3
是否有任何命令行工具可以将文件名解码为其 UTF-8 值:
- 0x66 0x6F 0x6F 0x2E 0x6D 0x70 0x33
- 0x62 0x61 0x72 0x2E 0x6D 0x70 0x33
答案1
获取十六进制字节值的标准 (POSIX/Unix) 命令是od
。
file=foo.mp3
printf %s "$file" | od -An -vtx1
其输出类似于:
66 6f 6f 2e 6d 70 33
$file
上面包含任意数组(对于除zsh
)字节。不考虑字符编码。
如果你想$file
包含一个数组人物(所以在语言环境的编码中)并且您想要以十六进制数字形式获取每个字符的 Unicode 代码点,在 Little-Endian 系统上,您可以执行以下操作:
printf %s "$file" | iconv -t UTF-32LE | od -An -vtx4
也可以看看:
printf %s "$file" | recode ..dump
或者:
printf %s "$file" | uconv -x hex/unicode
printf %s "$file" | uconv -x '([:Any:])>&hex/unicode($1)\n'
如果您希望字节值作为这些字符的 UTF-8 编码的十六进制数:
printf %s "$file" | iconv -t UTF-8 | od -An -vtx1
对于仅包含 ASCII 字符的类似内容foo.mp3
,它们都是等效的。
答案2
和perl
:
$ perl -CA -le 'print join " ", map { sprintf "0x%X", $_ } unpack "U*" for @ARGV' \
foo.mp3 bar.mp3 cường
0x66 0x6F 0x6F 0x2E 0x6D 0x70 0x33
0x62 0x61 0x72 0x2E 0x6D 0x70 0x33
0x63 0x1B0 0x1EDD 0x6E 0x67
如果将这些文件名列表存储在文件中,则:
perl -CI -lne 'print join " ", map { sprintf "0x%X", $_ } unpack "U*"' <file
答案3
我认为这可以通过一个简单的 Perl 脚本来完成:
perl -we 'foreach my $file (glob("*")) {
printf "0x%02X ", ord($_) foreach split//, $file; print "\n" }; '
当目录包含文件foo.mp3
和时,结果与您的输出类似bar.mp3
:
0x62 0x61 0x72 0x2E 0x6D 0x70 0x33
0x66 0x6F 0x6F 0x2E 0x6D 0x70 0x33
(我想glob()
对名字进行排序。)
解释:
foreach my $file (glob("*")) { # loop over all filenames in current directory
printf "0x%02X ", ord($_) # take the character as a number, and print in hex
foreach split//, $file; # .. after splitting the filename to characters
print "\n"; # add a newline
}
(* 以点开头的除外)
这只会打印文件名中的实际字节,因为它们存储在文件系统上。如果您的文件名称不是 UTF-8,该脚本将不会转换它们。
您还可以执行诸如通过管道传输ls
tood
或 之类的操作xxd
,这也可以处理文件名列表之外的其他数据,但会带来所有的问题与 read 一起出现ls
,并且很难将文件名分隔到不同的行。
答案4
使用普通的 Bash:
a=abcdefghij
for ((i=0;i<${#a};i++));do printf %02X \'${a:$i:1};done
6162636465666768696A
自定义printf
格式以满足您的需求。