Jak działają `>` i `>>`?

9

Próbowałem revutworzyć plik, a następnie potokować go, cat > same_fileale zamieniał się on w pusty plik.

Podczas gdy próbowałem rev file.txt | cat > file2.txt && mv file.txt file2.txt;, zadziałało.

Nawet rev file.txt | cat >> file.txt;pracował.

Ale kiedy próbowałem, rev file.txt | cat > file.txtnie udało się.

Vintux
źródło
Można również zostawić catna zewnątrz tak: rev file.txt > file2.txt && mv file2.txt file.txt. Jest to zbyteczne użyciecat . Pomijając to, oszczędzasz spawnowanie dodatkowego procesu.
matega

Odpowiedzi:

19

Podstawową rzeczą, którą musisz zrozumieć w tym przypadku między dwoma sposobami przekierowania (> i >>) jest:

>

Przekierowuje i zastępuje informacje tam, gdzie zostały wskazane. Dzieje się tak podczas odbierania jakichkolwiek informacji przez potok „|”

>>

Przekierowuje i konkatenuje do wskazanych informacji. Dzieje się tak podczas odbierania jakichkolwiek informacji przez potok „|”

W obu przypadkach, jeśli plik nie istnieje, zostanie utworzony zamiast tego. Tylko w „>>” informacje zostaną połączone, jeśli uruchomisz je ponownie w tym samym pliku. Za pomocą „>” po prostu zastąpisz wszystko, co zrobiłeś przy pierwszym uruchomieniu.

Ale tutaj jest umowa, gdy używasz tego samego pliku wejściowego co plik wyjściowy. W tym konkretnym przypadku, jeśli użyjesz „>”, usuniesz informację, którą część „wejściowa” musi przeanalizować, ponieważ plik wyjściowy „nadpisze” ją. Więc w:

rev file.txt | cat > file.txt

W „objaśnieniu w zwolnionym tempie” tak naprawdę dzieje się:

  1. revprzygotowuje się do odwrócenia zawartości file.txti przesłania jej do potoku
  2. Podczas revprzesyłania informacji do potoku potok przesyła je bezpośrednio do cat.
  3. Podczas catodbierania informacji automatycznie zastosuje je do tego, dla którego file.txtzostały ustawione.
  4. Słowo kluczowe to „while”, ponieważ wszystko dzieje się w tym samym czasie. Zobacz poniższe doskonałe komentarze Emila, aby lepiej zrozumieć tę część.
  5. catnie będzie czekać na revpotokowanie całego pliku. Po prostu zacznie się w momencie, gdy dotrze do niego pierwsza część informacji, co oznacza, że ​​w zależności od użytego symbolu otworzy połączenie file.txt.
  6. W tym przypadku, ponieważ użyłeś > zamiast >> , powłoka obetnie plik wyjściowy, co oznacza, że ​​otworzy i wyczyści informacje file.txtpodczas oczekiwania na dostęp do nowych informacji. Za pomocą >> otworzy połączenie file.txti poczeka na nowe informacje na temat ostatniej wykrytej linii.
  7. Ponieważ informacje zostały już wyczyszczone za file.txtpomocą > , revpostaram się to zrobić i nic nie dostanę, ponieważ catusuwam wszystko w ramach przygotowań do nowych informacji.

Dlaczego więc inni pracują po przeczytaniu powyższego. Z tego powodu:

rev file.txt | cat > file2.txt && mv file.txt file2.txt

Tutaj przesyłasz do cat, który wysyła informacje do innego pliku. W takim przypadku przetworzony plik wejściowy file.txtnie jest taki sam jak plik wyjściowy file2.txt. Po tym jesteś dosłownie nadpisywania cała file2.txtz file.txt, więc cały proces złożony przez catzostał usunięty. Zasadniczo całą linię można uprościć, cp file.txt file2.txtponieważ robi to samo, ponieważ file2.txtna końcu traci revi jest zastępowane mvpoleceniem.

rev file.txt | cat >> file.txt

W tym przypadku, gdy łącząc informacje do tego samego pliku. Czyli tylko otwiera połączenie z tym plikiem, ale nie usuwa informacji widocznych za pomocą jednego > . Końcowym rezultatem powinny być oryginalne informacje plus informacje odwrócone.

Luis Alvarado
źródło
5
Plik nie jest obcinany przez cat. Jest on obcinany przez powłokę, zanim jeszcze uruchomione zostanie jakiekolwiek polecenie w potoku.
Emil Jeřábek
Zgadza się, szukałem łatwiejszych słów do wyjaśnienia. Ponieważ trudno jest wyjaśnić, czy OP nie wie, co to za skorupa i tak dalej. Staramy się, aby był jak najbardziej „przyjazny”.
Luis Alvarado,
1
Cóż, tak naprawdę nie ma znaczenia, że ​​jest to wykonywane przez powłokę, ale że czas, który prezentujesz, jest zły. Obcinanie nie nastąpi w kroku 6, ale w kroku 0. rev file.txt | cat --bogus-option > file.txtspowoduje także obcięcie pliku, nawet jeśli kot nie będzie próbował go otworzyć.
Emil Jeřábek
@ EmilJeřábek masz rację. Jednak użytkownicy, którzy nie wiedzą, jak się zachowuje, będą mieli łatwiej, jeśli krok po kroku będziemy wykonywać tylko polecenia. Również twój przykład wciąż wysyła informacje do tego samego pliku, więc bash przeczyta całą linię, zobaczy wyjście i nadal otworzy ORAZ je skróci. Błąd polega na tym, że stderr wypisuje na standardowe wyjście.
Luis Alvarado,
4
Zobacz także moreutils , fantastyczny zestaw narzędzi (dostępny z repozytorium pakietów as moreutils), który zawiera spongenarzędzie zaprojektowane specjalnie do użycia w przypadku zastąpienia pliku wejściowego. Na przykład rev file.txt >file2.txt && mv file2.txt file.txtobejdzie się obejście rev file.txt | sponge file.txt, które będzie działać poprawnie, nawet jeśli istnieje już coś o nazwie file2.txt.
Daniel Wagner
9

Gdy powłoka widzi przekierowanie, najpierw otwiera odpowiednie pliki, przed wykonaniem któregokolwiek z poleceń. Tak więc, gdy robisz:

foo file.txt | bar > file.txt

Przekierowanie file.txtpowoduje, że jest ono obcinane przed foo uruchomieniem i można je odczytać file.txt. Na marginesie, dlatego nie możesz zrobić:

sed 'blah' file.txt > file.txt

I dlaczego sedma opcję edycji w miejscu.

Na koniec:

.. | cat > file.txt

jest bezużytecznym używaniem kota , zwłaszcza jeśli próbujesz czytać file.txtwcześniej.

Jeśli chcesz cofnąć plik w miejscu, nie ma skrótów . Możesz być w stanie użyć sztuczek sedlub awksztuczek z edycją lokalną.

muru
źródło
3

>to readresator (operator) wysyłający dane wyjściowe do czegoś innego
(wejście następnej komendy, drukarka ...)

W twoim przypadku dane wyjściowe trafiają do pliku file.txt, jeśli ten plik już istnieje, jest nadpisywany, jeśli nie, jest tworzony.

>>jest operatorem dołączającym, jeśli file.txtjuż istnieje, wynik jest dołączany na końcu pliku. jeśli plik nie istnieje, jest tworzony, a dane wyjściowe zapisywane w nowym pliku, tak samo jak >(redirector).

Ken Mollerup
źródło
Wydaje się, że PO to zrozumiał. Zamieszanie wydaje się wynikać tylko z tego samego pliku znajdującego się po obu stronach operatorów >i >>.
bzlm
0

Możesz używać Vima w trybie Ex:

ex -sc '%!rev' -cx file.txt
  1. % wybierz wszystkie linie

  2. ! Uruchom polecenie

  3. x Zapisz i zamknij

Steven Penny
źródło