Och, ale sponge
to nie jedyna opcja; nie musisz tego robić moreutils
, aby to działało poprawnie. Każdy mechanizm będzie działał, o ile spełnia następujące dwa wymagania:
- Przyjmuje nazwę pliku wyjściowego jako parametr.
- Tworzy plik wyjściowy dopiero po przetworzeniu wszystkich danych wejściowych.
Widzisz, dobrze znanym problemem, do którego odnosi się OP, jest to, że powłoka utworzy wszystkie pliki, które są niezbędne do działania potoków, zanim zaczną nawet wykonywać polecenia w potoku, więc to powłoka faktycznie obcina plik wyjściowy (który niestety jest również plikiem wejściowym), zanim którekolwiek z poleceń zdążyło się uruchomić.
tee
Komenda nie działa, mimo że spełnia pierwszy warunek, ponieważ nie spełnia drugi warunek: będzie zawsze natychmiast utworzyć plik wyjściowy przy starcie, więc jest to w istocie tak źle, jak tworząc rurę prosto do pliku wyjściowego. (Jest tak naprawdę gorzej, ponieważ jego użycie wprowadza niedeterministyczne losowe opóźnienie przed obcięciem pliku wyjściowego, więc możesz pomyśleć, że działa, podczas gdy w rzeczywistości nie działa).
Aby rozwiązać ten problem, potrzebujemy tylko polecenia, które zbuforuje wszystkie dane wejściowe przed wygenerowaniem danych wyjściowych i które jest w stanie zaakceptować nazwę pliku wyjściowego jako parametr, dzięki czemu nie musimy przesyłać danych wyjściowych do plik wyjściowy. Jednym z takich poleceń jest shuf
. Tak więc następujące rzeczy osiągną to samo, sponge
co:
shuf --output=file --random-source=/dev/zero
W --random-source=/dev/zero
części sztuczki shuf
język robi jego rzecz bez jakiegokolwiek szuranie w ogóle, więc będzie buforować swój wkład bez zmieniania go.