Использование одного и того же файла для stdin и stdout с перенаправлением - PullRequest
13 голосов
/ 09 октября 2010

Я пишу приложение, которое действует как фильтр: оно читает входные данные из файла (stdin), обрабатывает и записывает выходные данные в другой файл (stdout).Входной файл полностью читается перед тем, как приложение начинает записывать выходной файл.

Поскольку я использую stdin и stdout, я могу запустить это так:

$ ./myprog <file1.txt >file2.txt

Работает нормально, но если я попытаюсь использовать один и тот же файл для ввода и вывода (то есть для чтения из файла и записи в один и тот же файл), например, так:

$ ./myprog <file.txt >file.txt

он очищает file.txt передПрограмма имеет возможность прочитать его.

Есть ли способ сделать что-то подобное в командной строке в Unix?

Ответы [ 3 ]

17 голосов
/ 28 сентября 2013

В пакете moreutils есть утилита губки:

./myprog < file.txt | sponge file.txt

Цитировать руководство:

Губка читает стандартный ввод и записывает его вуказанный файл.В отличие от перенаправления оболочки, губка впитывает весь свой ввод перед открытием выходного файла.Это позволяет создавать конвейеры, которые читают и записывают в один и тот же файл.

13 голосов
/ 09 октября 2010

Оболочка - это то, что поглощает ваш выходной файл, так как она готовит выходные файловые дескрипторы перед выполнением вашей программы.Невозможно заставить вашу программу прочитать входные данные до того, как оболочка захлопнет файл в одной командной строке оболочки.

Вам нужно использовать две команды, либо переместить, либо скопировать файл перед чтением:

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
8 голосов
/ 10 мая 2012

Для решения чисто академического характера:

$ ( unlink file.txt && ./myprog >file.txt ) <file.txt

Возможные проблемные побочные эффекты:

  • Если ./myprog терпит неудачу, вы уничтожаете свой ввод. (Естественно ...)
  • ./myprog запускается из подоболочки (используйте { ... ; } вместо ( ... ), чтобы избежать.)
  • file.txt становится новым файлом с новым индексом и правами доступа к файлу.
  • Вам необходимо +w разрешение на размещение в каталоге file.txt.
...