如何使用命令行解码文件名?

如何使用命令行解码文件名?

是否可以通过命令行解码文件名?

假设我有以下两个文件:

  • 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,该脚本将不会转换它们。

您还可以执行诸如通过管道传输lstood或 之类的操作xxd,这也可以处理文件名列表之外的其他数据,但会带来所有的问题与 read 一起出现ls,并且很难将文件名分隔到不同的行。

答案4

使用普通的 Bash:

a=abcdefghij    
for ((i=0;i<${#a};i++));do printf %02X \'${a:$i:1};done
6162636465666768696A

自定义printf格式以满足您的需求。

相关内容