Это очень возможно, вам просто нужно убедиться, что к моменту написания вывода вы записываете его в другой файл. Это можно сделать, удалив файл после открытия ему файлового дескриптора, но перед записью в него:
exec 3<file ; rm file; COMMAND <&3 >file ; exec 3>&-
Или построчно, чтобы лучше понять:
exec 3<file
rm file
COMMAND <&3 >file
exec 3>&-
Это по-прежнему рискованно, потому что, если COMMAND не работает должным образом, вы потеряете содержимое файла. Это можно уменьшить, восстановив файл, если КОМАНДА возвращает ненулевой код выхода:
exec 3<file ; rm file; COMMAND <&3 >file || cat <&3 >file ; exec 3>&-
Мы также можем определить функцию оболочки, чтобы упростить ее использование:
replace() { exec 3<$1 ; rm $1; ${@:2} <&3 >$1 || cat <&3 >$1 ; exec 3>&- }
Пример :
$ echo aaa > test
$ replace test tr a b
$ cat test
bbb
Также обратите внимание, что при этом будет сохранена полная копия исходного файла (до закрытия третьего файлового дескриптора). Если вы используете Linux, и файл, который вы обрабатываете, слишком велик, чтобы дважды поместиться на диске, вы можете проверить этот скрипт, который будет перенаправлять файл в указанную команду блок за блоком, освобождая уже обработанные блоки. Как всегда, прочтите предупреждения на странице использования.