Supprimer les n premiers octets des files

J'ai un problème extrême, et toutes les solutions que je peux imaginer sont compliquées. Selon mon expérience UNIX / Linux, il doit y avoir un moyen facile.

Je veux supprimer les 31 premiers octets de chaque file dans /foo/ . Chaque file est assez long. Eh bien, je suis sûr que quelqu'un va me livrer une solution étonnamment facile que je ne peux pas imaginer. Peut-être awk?

 for file in /foo/* do if [ -f "$file" ] then dd if="$file" of="$file.truncated" bs=31 skip=1 && mv "$file.truncated" "$file" fi done 

ou plus vite, grâce à la suggestion de Gilles:

 for file in /foo/* do if [ -f $file ] then tail +32c $file > $file.truncated && mv $file.truncated $file fi done 

Note: La queue Posix spécifie "-c +32" au lieu de "+ 32c" mais la queue par défaut de Solaris ne l'aime pas:

  $ /usr/bin/tail -c +32 /tmp/foo > /tmp/foo1 tail: cannot open input 

/usr/xpg4/bin/tail est très bien avec les deux syntaxes.

Les commands suivantes coupent les 31 premiers octets à partir du $file (en utilisant $file~ comme copy temporaire):

 dd if="$file" of="$file~" bs=1 skip=31 mv "$file~" "$file" 

Vous n'avez qu'à listr ou find tous les files sous /foo/ et exécuter les deux ci-dessus pour chaque $file trouvé.

tail -c +32 affiche son input less les 31 premiers octets. (Oui, l'argument est désactivé d'un.) Pour éditer un file, utilisez l'éponge dans une boucle, ou si vous ne l'avez pas et ne voulez pas déranger, faites son travail dans le shell:

 for x in /foo/*; do tail -c +32 "$x" | sponge "$x"; done for x in /foo/*; do tail -c +32 "$x" >"$x.new" && mv "$x.new" "$x"; done 

Si les commands sont interrompues pour une raison quelconque (par exemple une panne de courant), il peut être difficile de déterminer où vous vous êtes arrêté. Écrire les nouveaux files dans un directory séparé faciliterait les choses.

 mkdir /foo.tmp cd /foo for x in *; do tail -c +42 -- "$x" >"/foo.tmp/$x" && rm -- "$x"; done mv /foo.tmp/* /foo rmdir /foo.tmp 

Si les files sont vraiment volumineux (comme dans, assez grand pour avoir deux copys d'un seul même est un problème), vous pouvez utiliser l' une des techniques mentionnées dans ce fil .

Vous pouvez utiliser Vim en mode Ex:

 for each in /foo/* do ex -sc '%!tail -c+32' -cx "$each" done 
  1. % select toutes les lignes

  2. ! exécuter la command

  3. x sauvegarder et fermer