Этот вопрос натолкнул на мысль, которую я не был уверен, что правильно понял. Я знаю, что использовать конвейеры вроде cat myfile | grep -v mypattern> myfile
из-за того, как настроены дескрипторы файлов.Однако почему мы не можем просто использовать cat myfile | grep -v mypattern | tee myfile> / dev / null
, чтобы изменить файл на месте? Есть ли какие-нибудь простые примеры, когда это не удается?
В частности, приводит ли это к повреждению или это больше не редактирование на месте, а перезапись?
Обновляя вопрос, я был бы признателен, если бы ответы учли и это тоже :
Есть ли проблемы с использованием cat myfile | grep -v mypattern | bash -c 'rm myfile; cat> myfile '
?
Проблема в том, что вы не можете гарантировать, что будет выполнено первым. Поэтому вам нужно отложить отключение и запись в файл до тех пор, пока вы не будете абсолютно уверены, что файл открыт для чтения.
Это буферизует файл в ОЗУ перед его записью.
cat foo | perl -e 'undef $/; @out=<>; open WRT,">",shift; print WRT @out' foo
Преимущество: сохраняет права доступа к foo. В случае прерывания вы не потеряли исходный файл foo.
Недостаток: foo должен умещаться в ОЗУ.
Это откроет файл для чтения, удалит его и cat
из него. Параллельно он ждет, пока файл исчезнет, а когда он исчезнет , перейдет к нему
.
(rm foo; cat) < foo | (perl -e 'while(-e "foo"){}'; cat >foo)
Преимущество: Краткое. Работает с файлами размером больше ОЗУ.
Недостаток: foo исчезает при запуске.
(mv foo bar; cat) < foo | (perl -e 'while(-e "foo"){}'; cat >foo && rm bar)
Преимущество: работает с файлами, размер которых превышает размер ОЗУ. В случае неудачи foo сохраняется в качестве резервной копии в bar.
Вы не можете просто сделать это, потому что команда tee
перезаписывает файл, делая его короче (возможно) и удаляя cat
возможность чтения данных, которые были в файле.
Если бы вы могли убедиться, что программы, такие как tee
, открывали новый файл, и , если оболочка гарантировала, что cat
открывает свой сначала скопируйте, затем вы можете скопировать из старого (фактически удаленного) файла в новый. Но есть много «если» и мало гарантий.
Вы можете предположить, например, что cat
будет запускаться первым, а tee
позже (когда это необходимо для сбора данных). Но оболочка запускает обе, и если tee
не ожидает ввода до запуска cat
, запись может завершиться ошибкой (поскольку никто не ждет, и эти байты имеют некуда идти). Проще заставить процессы ждать чтения
, чем записи
.