tl; dr
Nie. >>
Zasadniczo „zawsze dąży do końca pliku”, >
zachowując wskaźnik do ostatniej zapisanej lokalizacji.
Pełna odpowiedź
(Uwaga: wszystkie moje testy przeprowadzono na Debian GNU / Linux 9).
Kolejna różnica
Nie, nie są równoważne. Jest jeszcze jedna różnica. Może się manifestować niezależnie od tego, czy plik docelowy istniał wcześniej, czy nie.
Aby to zaobserwować, uruchom proces, który generuje dane i przekierowuje do pliku za pomocą >
lub >>
(np pv -L 10k /dev/urandom > blob
.). Pozwól mu działać i zmień rozmiar pliku (np. Za pomocą truncate
). Zobaczysz, że >
utrzymuje (rosnące) przesunięcie, >>
zawsze dołączając do końca.
- Jeśli plik zostanie obcięty do mniejszego rozmiaru (może być zerowy)
>
nie obchodzi mnie to, napisze w pożądanym miejscu, jakby nic się nie stało; tuż po obcięciu przesunięcia poza koniec pliku spowoduje to, że plik odzyska swój stary rozmiar i powiększy się dalej, brakujące dane zostaną wypełnione zerami (jeśli to możliwe, w niewielkim stopniu);
>>
dołącza się do nowego końca, plik wzrośnie ze swojego obciętego rozmiaru.
- Jeśli powiększysz plik
>
nie obchodzi mnie to, napisze w pożądanym miejscu, jakby nic się nie stało; zaraz po zmianie rozmiaru przesunięcie znajduje się gdzieś w pliku, spowoduje to, że plik przestanie rosnąć przez jakiś czas, dopóki przesunięcie nie osiągnie nowego końca, wtedy plik wzrośnie normalnie;
>>
dołącza się do nowego końca, plik wzrośnie z powiększonego rozmiaru.
Innym przykładem jest dodanie (z osobnym >>
) czegoś dodatkowego, gdy proces generowania danych jest uruchomiony i zapisuje się do pliku. Jest to podobne do powiększania pliku.
- Proces generowania
>
zapisuje z pożądanym przesunięciem i ostatecznie nadpisuje dodatkowe dane.
- Proces generowania
>>
pomija nowe dane i dołącza je obok (mogą wystąpić warunki wyścigu, dwa strumienie mogą się przeplatać, nadal nie należy nadpisywać żadnych danych).
Przykład
Czy to ma znaczenie w praktyce? Oto pytanie :
Pracuję nad procesem, który generuje dużo danych wyjściowych na standardowym wyjściu. Przesyłanie wszystkiego do pliku [...] Czy mogę użyć jakiegoś programu do obracania dzienników?
Ta odpowiedź mówi, że rozwiązanie jest logrotate
z copytruncate
opcją, która działa tak:
Obetnij oryginalny plik dziennika po utworzeniu kopii, zamiast przenosić stary plik dziennika i opcjonalnie utworzyć nowy.
Zgodnie z tym, co napisałem powyżej, przekierowanie za pomocą >
spowoduje, że ścięty dziennik stanie się duży w krótkim czasie. Rzadkość pozwoli zaoszczędzić dzień, nie należy marnować znacznej ilości miejsca na dysku. Niemniej jednak każdy kolejny dziennik będzie zawierał coraz więcej zer wiodących, które są całkowicie niepotrzebne.
Ale jeśli logrotate
tworzy kopie bez zachowania rzadkości, te wiodące zera będą wymagały coraz więcej miejsca na dysku za każdym razem, gdy kopia zostanie wykonana. Nie badałem zachowania narzędzia, może być wystarczająco inteligentne z rzadkością lub kompresją w locie (jeśli kompresja jest włączona). Mimo to zera mogą powodować problemy lub w najlepszym razie być neutralne; nic dobrego w nich.
W takim przypadku użycie >>
zamiast zamiast >
jest znacznie lepsze, nawet jeśli plik docelowy ma być jeszcze utworzony.
Występ
Jak widzimy, dwaj operatorzy zachowują się inaczej, nie tylko na początku, ale także później. Może to powodować pewne (subtelne?) Różnice w wydajności. Na razie nie mam znaczących wyników testów na poparcie lub obalenie go, ale myślę, że nie powinieneś automatycznie zakładać, że ich wydajność jest ogólnie taka sama.
>>
jest w istocie „zawsze dążyć do końca pliku” podczas>
utrzymuje wskaźnik do ostatniego pisemnego lokalizacji. Wygląda na to, że mogą występować pewne subtelne różnice w wydajności w sposobie ich działania ...>>
używaO_APPEND
flagi doopen()
. I faktycznie>
używaO_TRUNC
, podczas gdy>>
nie. KombinacjaO_TRUNC | O_APPEND
byłaby również możliwa, język powłoki po prostu nie zapewnia tej funkcji.O_APPEND
zlseek()
nichwrite()
byłaby jednak inna, pojawiłby się dodatkowy koszt wywołania systemowego. (I oczywiście nie zadziałałoby, ponieważ może towrite()