Це дуже можливо, вам просто потрібно переконатися, що до того часу, коли ви напишете вихідні дані, ви будете писати його в інший файл. Це можна зробити, видаливши файл після відкриття дескриптора файлу, але перед тим, як написати в нього:
exec 3<file ; rm file; COMMAND <&3 >file ; exec 3>&-
Або рядок за рядком, щоб краще це зрозуміти:
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
Це все ще ризикована справа, оскільки якщо COMMAND не працює належним чином, ви втратите вміст файлу. Це можна пом'якшити, відновивши файл, якщо COMMAND повертає ненульовий код виходу:
exec 3<file ; rm file; COMMAND <&3 >file || cat <&3 >file ; exec 3>&-
Ми також можемо визначити функцію оболонки, щоб полегшити її використання:
# Usage: replace FILE COMMAND
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, а файл, який ви обробляєте, занадто великий, щоб двічі поміститися на диску, ви можете перевірити цей скрипт, який передаватиме файл до вказаної команди покроково, відміняючи вже оброблений блоків. Як завжди, прочитайте попередження на сторінці використання.