Điều này rất có thể xảy ra, bạn chỉ cần đảm bảo rằng vào thời điểm bạn ghi đầu ra, bạn đang ghi nó vào một tệp khác. Điều này có thể được thực hiện bằng cách xóa tệp sau khi mở bộ mô tả tệp cho nó, nhưng trước khi ghi vào nó:
exec 3<file ; rm file; COMMAND <&3 >file ; exec 3>&-
Hoặc từng dòng, để hiểu rõ hơn:
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
Đó vẫn là một điều rủi ro để làm, bởi vì nếu COMMAND không chạy đúng cách, bạn sẽ mất nội dung tệp. Điều đó có thể được giảm thiểu bằng cách khôi phục tệp nếu COMMAND trả về mã thoát khác 0:
exec 3<file ; rm file; COMMAND <&3 >file || cat <&3 >file ; exec 3>&-
Chúng tôi cũng có thể xác định một hàm shell để giúp sử dụng dễ dàng hơn:
# Usage: replace FILE COMMAND
replace() { exec 3<$1 ; rm $1; ${@:2} <&3 >$1 || cat <&3 >$1 ; exec 3>&- }
Thí dụ :
$ echo aaa > test
$ replace test tr a b
$ cat test
bbb
Ngoài ra, lưu ý rằng điều này sẽ giữ một bản sao đầy đủ của tệp gốc (cho đến khi bộ mô tả tệp thứ ba bị đóng). Nếu bạn đang sử dụng Linux và tệp bạn đang xử lý quá lớn để có thể vừa hai lần trên đĩa, bạn có thể kiểm tra tập lệnh này sẽ chuyển tệp đến từng khối lệnh được chỉ định trong khi hủy phân bổ tệp đã được xử lý các khối. Như mọi khi, hãy đọc các cảnh báo trong trang sử dụng.