Je résolvais un défi où j'ai trouvé un fichier de données sans extension de fichier. La file
commande montre qu'il s'agit d'un data file (application/octet-stream)
. La hd
commande affiche GNP. dans la dernière ligne. Donc, si j'inverse ce fichier, j'obtiendrai le fichier au format .PNG , j'ai cherché partout mais je n'ai pas trouvé de solution expliquant comment inverser le contenu d'un fichier binaire.
11
Dans
zsh
(le seul shell capable de traiter en interne les données binaires (sauf si vous voulez considérer l'approche de codage base64 de ksh93 )):LC_ALL=C
: les caractères sont des octets$mapfile[file.gnp]
: contenu dufile.gnp
fichiers::
: divise la chaîne en ses constituants d'octetOa
: inverserO
lea
rder sur l' indice de rray ce tableaula source
zsh
n'est pas le seul shell capable de gérer des données binaires.Voici une façon d'inverser un fichier binaire en utilisant
ksh93
. J'ai laissé le code "lâche" pour le rendre plus facile à comprendre.la source
read
ci-dessus ne devrait rien lire car il se fait à la fin du fichier.strace
etksh93
semble se comporter très bizarrement, où il cherche partout dans le fichier et lit de grandes quantités à l'époque. Peut-être une variante de github.com/att/ast/issues/15strace
le script pour voir ce que je veux dire.ksh93
lit les fichiers des milliers de fois. Par exemple, avant de lire le premier octet, il recherche 64 Ko à la fin du fichier, lit 64 Ko, puis recherche avant le dernier octet et lit 1 octet et fait quelque chose de similaire pour chaque octet. Notez que ce que vous pouvez faire avec ces chaînes encodées en base64 est limité, donc si vous lisez plus d'un octet à la fois, il sera plus difficile d'extraire les octets individuels de cela.Avec perl:
Test de performance:
Résultat:
perl -0777 -F
la plus lente.xxd
est la plus lente.Remarque: les délais
diff
doivent être les mêmes pour toutes les solutions, car la sortie doit être la même.la source
perl
. Je n'avais pas réalisé à l'époque quereverse
je pouvais aussi inverser les chaînes, donc le fractionnement n'avait pas beaucoup de sens et votre version est bien meilleure.J'ai essayé ce qui suit:
L'idée est de forcer 'tac' en utilisant n'importe quel caractère comme séparateur. J'ai essayé cela sur un fichier binaire et cela semblait fonctionner mais toute confirmation serait appréciée.
Le principal avantage est qu'il ne charge pas le fichier en mémoire.
la source
tac
8.28) lorsque l'entrée contient des caractères de nouvelle ligne.printf '1\n2' | tac -rs . | od -vAn -tc
sorties\n 2 1
au lieu de2 \n 1
. Vous auriez également besoinLC_ALL=C
ou.
pourriez faire correspondre des caractères multi-octets.LC_ALL=C tac -rs $'.\\|\n'
semble fonctionner cependant.