Como posso decodificar um nome de arquivo usando a linha de comando?

6

é possível decodificar um nome de arquivo por linha de comando?

Suponha que eu tenha os dois arquivos a seguir:

  • foo.mp3
  • bar.mp3

Existe alguma ferramenta de linha de comando que decodifica os nomes dos arquivos em seus valores UTF-8:

  • 0x66 0x6F 0x6F 0x2E 0x6D 0x70 0x33
  • 0x62 0x61 0x72 0x2E 0x6D 0x70 0x33
por Grynium 16.03.2017 / 15:37

4 respostas

14

O comando padrão (POSIX / Unix) para obter os valores de byte como números hexadecimais é od .

file=foo.mp3
printf %s "$file" | od -An -vtx1

O que dá uma saída semelhante a:

 66 6f 6f 2e 6d 70 33

$file acima contém uma matriz arbitrária de (não-NUL para shells diferentes de zsh ) bytes . A codificação de caracteres não entra em consideração.

Se você quiser que $file contenha uma matriz de caracteres (portanto, na codificação da localidade) e deseja obter os pontos de código Unicode para cada um deles como números hexadecimais, em um Little- Sistema Endian, você poderia fazer:

printf %s "$file" | iconv -t UTF-32LE | od -An -vtx4

Veja também:

printf %s "$file" | recode ..dump

Ou:

printf %s "$file" | uconv -x hex/unicode
printf %s "$file" | uconv -x '([:Any:])>&hex/unicode($1)\n'

Se você quisesse os valores de bytes como números hexadecimais da codificação UTF-8 desses caracteres:

printf %s "$file" | iconv -t UTF-8 | od -An -vtx1

Para algo como foo.mp3 que contém apenas caracteres ASCII, todos serão equivalentes.

    
por 16.03.2017 / 16:41
4

com 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

Se você armazenar essa lista de nomes de arquivos em um arquivo, então:

perl -CI -lne 'print join " ", map { sprintf "0x%X", $_ } unpack "U*"' <file
    
por 16.03.2017 / 16:10
4

Com Bash simples:

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

Personalize o formato printf para atender às suas necessidades.

    
por 16.03.2017 / 16:11
3

Acho que isso pode ser feito com um script Perl simples:

perl -we 'foreach my $file (glob("*")) { 
   printf "0x%02X ", ord($_) foreach split//, $file; print "\n" }; '

resultando em uma saída semelhante à sua quando o diretório contém arquivos foo.mp3 e bar.mp3 :

0x62 0x61 0x72 0x2E 0x6D 0x70 0x33 
0x66 0x6F 0x6F 0x2E 0x6D 0x70 0x33 

(acho que glob() classifica os nomes.)

Explicação:

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
}

(* exceto aqueles que começam com um ponto)

Isso apenas imprimirá os bytes reais nos nomes dos arquivos, pois eles são armazenados no sistema de arquivos. Se você tiver arquivos cujos nomes não estejam em UTF-8, o script não os converterá.

Você também pode fazer algo como canalizar a saída de ls para od ou xxd , o que também funcionaria com outros dados além das listas de nomes de arquivos, mas traria todos os problemas que vêm com a leitura de ls , e seria difícil separar os nomes dos arquivos em linhas diferentes.

    
por 16.03.2017 / 15:49