2010-10-09 20 views
12

Piszę aplikację, która działa jak filtr: odczytuje dane wejściowe z pliku (stdin), przetwarza i zapisuje dane wyjściowe do innego pliku (stdout). Plik wejściowy zostanie całkowicie odczytany, zanim aplikacja rozpocznie zapisywanie pliku wyjściowego.Używanie tego samego pliku dla stdin i stdout z przekierowaniem

Ponieważ używam stdin i stdout, mogę uruchomić to tak:

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

To działa dobrze, ale gdy próbuję użyć tego samego pliku jako wejścia i wyjścia (czyli: czytaj z pliku i zapisu do tego samego pliku), jak poniżej:

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

czyści file.txt zanim program ma szansę, aby ją przeczytać.

Czy jest jakiś sposób mogę zrobić coś takiego w linii poleceń w systemie Unix?

Odpowiedz

13

Powłoka jest tym, co powoduje zbicie pliku wyjściowego, ponieważ przygotowuje ona uchwyty plików wyjściowych przed wykonaniem programu przez. Nie ma sposobu, aby twój program odczytał dane wejściowe, zanim powłoka przerwie plik w pojedynczą linię poleceń powłoki.

Trzeba użyć dwóch poleceń ruchome bądź kopiując plik przed przeczytaniem go:

mv file.txt filecopy.txt 
./myprog <filecopy.txt> file.txt 

Albo wyprowadzania do kopii, a następnie zastąpienie oryginalnego:

./myprog <file.txt> filecopy.txt 
mv filecopy.txt file.txt 

jeśli potrafisz Aby to zrobić, musisz przekazać nazwę pliku do swojego programu, który otwiera plik w trybie odczytu/zapisu i wewnętrznie obsługuje wszystkie wejścia/wyjścia.

./myprog file.txt     # reads and writes according to its own rules 
8

rozwiązania o charakterze czysto akademickiej:

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

Ewentualnie problematyczne skutki uboczne to:

  • ./myprog Jeśli nie powiedzie się, zniszczyć swój wkład. (Naturalnie ...)
  • ./myprog biegnie od podpowłoce (użyj { ... ; } zamiast (...) uniknąć.)
  • file.txt staje się nowy plik z nowymi uprawnieniami iwęźle i plików.
  • Musisz mieć pozwolenie na +w na obudowie katalogu file.txt.
+0

Dziwne. Dlaczego '$ (./myprog> file.txt) TheoYou

+0

Twój przykład robi to, ponieważ '> plik.txt' obcina zawartość pliku.txt i jest to nawiasem mówiąc ten sam plik, z którego odczytuje plik' plik.txt' tworzy nowy * plik * (inny i-węzeł na tej samej ścieżce), który jest oddzielny od tego, z jakiego ' antak

+0

Więc wszystko, co musimy zrobić, to sami uruchomić sub-powłokę. Myślę, że znam odpowiedź, ale nadal nie jestem pewna, dlaczego ... – TheoYou

15

Jest to narzędzie gąbka w moreutils opakowaniu:

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

Cytując instrukcję:

Sponge czyta standardowe wejście i zapisuje go do określonego pliku. W przeciwieństwie do przekierowania powłoki, gąbka wchłania wszystkie dane wejściowe przed otwarciem pliku wyjściowego. Umożliwia to tworzenie potoków odczytujących i zapisujących do tego samego pliku.

+1

Proszę, rozwiąż swoją odpowiedź. – Beppe

Powiązane problemy