Использование того же файла для stdin и stdout с перенаправлением
Я пишу приложение, которое действует как фильтр: он читает ввод из файла (stdin), обрабатывает и записывает вывод в другой файл (stdout). Входной файл полностью считывается до того, как приложение начнет запись выходного файла.
Поскольку я использую stdin и stdout, я могу запустить, как это:
$ ./myprog <file1.txt >file2.txt
Он отлично работает, но если я пытаюсь использовать тот же файл, что и вход и выход (то есть: чтение из файла и запись в тот же файл), например:
$ ./myprog <file.txt >file.txt
он очищает file.txt
, прежде чем программа имеет возможность прочитать его.
Есть ли способ сделать что-то подобное в командной строке в Unix?
Ответы
Ответ 1
Оболочка - это то, что захватывает ваш выходной файл, поскольку он готовит дескрипторы выходных файлов перед выполнением вашей программы. Нет способа заставить вашу программу читать ввод до того, как оболочка скроет файл в одной командной строке оболочки.
Вам нужно использовать две команды: перемещение или копирование файла перед его чтением:
mv file.txt filecopy.txt
./myprog < filecopy.txt > file.txt
Или вывести копию и затем заменить оригинал:
./myprog < file.txt > filecopy.txt
mv filecopy.txt file.txt
Если вы не можете этого сделать, вам необходимо передать имя файла в вашу программу, которая откроет файл в режиме чтения/записи и будет обрабатывать все внутренние операции ввода/вывода.
./myprog file.txt # reads and writes according to its own rules
Ответ 2
В утилите moreutils имеется утилита sponge:
./myprog < file.txt | sponge file.txt
Процитировать руководство:
Sponge считывает стандартный ввод и записывает его в указанный файл. В отличие от перенаправления оболочки, губка впитывает весь свой вход перед открытием выходного файла. Это позволяет конструировать конвейеры, которые считывают и записывают в один и тот же файл.
Ответ 3
Для решения чисто академического характера:
$ ( unlink file.txt && ./myprog >file.txt ) <file.txt
Возможно, проблемные побочные эффекты:
- Если
./myprog
терпит неудачу, вы уничтожаете свой вход. (Естественно...)
-
./myprog
выполняется из подоболочки (используйте { ... ; }
вместо ( ... )
, чтобы этого избежать.)
-
file.txt
становится новым файлом с новыми правами доступа к файлам и файлам.
- Вам нужно разрешение
+w
на корпус каталога file.txt
.