July 16, 2009

Posso maneggiare file binari mediante script di shell?

L’unica shell di cui sia a conoscenza che permetta di gestire bene file binari, ovvero contenenti il carattere NULL (’\0′) è zsh.

Ecco una breve dimostrazione fra le shell più comuni (dash, busybox ash e bash):

[email protected] ~ % busybox sh -c 'a=$(printf "\001\002\000\003\004") ; echo -n "$a"' | hexdump -v -e '1/1 "%.2x "'
01 02 03 04

E che fine ha fatto lo 0? Si è perso!

[email protected] ~ % dash -c 'a=$(printf "\001\002\000\003\004") ; echo -n "$a"' | hexdump -v -e '1/1 "%.2x "'
01 02 03 04

Esattamente come sopra

[email protected] ~ % bash -c 'a=$(printf "\001\002\000\003\004") ; echo -n "$a"' | hexdump -v -e '1/1 "%.2x "'
01 02 03 04

Pure qui :)

Invece usando zsh, tutto cambia:

[email protected] ~ % zsh -c 'a=$(printf "\001\002\000\003\004") ; echo -n "$a"' | hexdump -v -e '1/1 "%.2x "'
01 02 00 03 04

Ecco il carattere ‘\0′!

Anche le operazioni a stringa si possono effettuare pure avendo il NULL, per esempio contare il numero di caratteri nella stringa:

[email protected] ~ % dash -c 'a=$(printf "\001\002\000\003\004") ; echo "${#a}"'
4

Con dash, bash e busybox sh conta 4 caratteri, mentre zsh ne conta, giustamente, 5:

[email protected] ~ % zsh -c 'a=$(printf "\001\002\000\003\004") ; echo "${#a}"'
5

La stessa cosa con operazioni più complesse, come il reverse della stringa:

[email protected] ~ % zsh -c 'a=$(printf "\001\002\000\003\004") ; echo -n "${(j::)${(@Oa)${(s::):-$a}}}"' | hexdump -v -e '1/1 "%.2x "'
04 03 00 02 01