C'est très possible, il vous suffit de vous assurer qu'au moment où vous écrivez la sortie, vous l'écrivez dans un fichier différent. Cela peut être fait en supprimant le fichier après avoir ouvert un descripteur de fichier, mais avant d'y écrire:
exec 3<file ; rm file; COMMAND <&3 >file ; exec 3>&-
Ou ligne par ligne, pour mieux le comprendre:
exec 3<file # open a file descriptor reading 'file'
rm file # remove file (but fd3 will still point to the removed file)
COMMAND <&3 >file # run command, with the removed file as input
exec 3>&- # close the file descriptor
C'est toujours une chose risquée à faire, car si COMMAND ne fonctionne pas correctement, vous perdrez le contenu du fichier. Cela peut être atténué en restaurant le fichier si COMMAND renvoie un code de sortie différent de zéro:
exec 3<file ; rm file; COMMAND <&3 >file || cat <&3 >file ; exec 3>&-
Nous pouvons également définir une fonction shell pour faciliter son utilisation:
# Usage: replace FILE COMMAND
replace() { exec 3<$1 ; rm $1; ${@:2} <&3 >$1 || cat <&3 >$1 ; exec 3>&- }
Exemple :
$ echo aaa > test
$ replace test tr a b
$ cat test
bbb
Notez également que cela conservera une copie complète du fichier d'origine (jusqu'à ce que le troisième descripteur de fichier soit fermé). Si vous utilisez Linux et que le fichier que vous traitez est trop volumineux pour tenir deux fois sur le disque, vous pouvez consulter ce script qui dirigera le fichier vers la commande spécifiée bloc par bloc tout en annulant le déjà traité blocs. Comme toujours, lisez les avertissements dans la page d'utilisation.