Come funzionano `>` e `>>`?


9

Ho provato a revun file e poi a pipe cat > same_filema si stava trasformando in un file vuoto.

Mentre ho provato rev file.txt | cat > file2.txt && mv file.txt file2.txt;ha funzionato.

Ha persino rev file.txt | cat >> file.txt;funzionato.

Ma quando l'ho provato rev file.txt | cat > file.txtè fallito.


È anche possibile lasciare catfuori come questo: rev file.txt > file2.txt && mv file2.txt file.txt. Questo è un uso superfluo dicat . Lasciandolo fuori risparmi generando un ulteriore processo.
matega,

Risposte:


19

La cosa di base che devi cogliere in questo caso tra entrambi i modi di reindirizzamento (> e >>) è:

>

Reindirizza e sovrascrive le informazioni in cui è stato indicato. Ciò accade durante la ricezione di qualsiasi informazione tramite pipe "|"

>>

Reindirizza e concatena le informazioni a cui è stato puntato. Ciò accade durante la ricezione di qualsiasi informazione tramite pipe "|"

In entrambi i casi, se il file non esiste, verrà invece creato. Solo su ">>" le informazioni verranno concatenate se eseguite nuovamente sullo stesso file. Con ">" sovrascriveresti semplicemente tutto ciò che hai fatto alla prima esecuzione.

Ma ecco l'affare quando si utilizza lo stesso file di input del file di output. In quel caso particolare, se usi ">" rimuoveresti le informazioni che la parte "input" deve analizzare, dal momento che il file di output lo "sovrascriverà". Quindi in:

rev file.txt | cat > file.txt

Ciò che sta realmente accadendo nella "spiegazione al rallentatore" è:

  1. revsi prepara a invertire il contenuto file.txte inviarlo alla pipe
  2. Durante l' revinvio delle informazioni alla pipe, pipe le trasmette direttamente a cat.
  3. Mentre catriceve le informazioni, le applicherà automaticamente a quelle con cui file.txtè stato impostato.
  4. La parola chiave qui è "while", perché tutto sta accadendo contemporaneamente. Si prega di vedere gli eccellenti commenti qui sotto di Emil per avere una comprensione più profonda di questa parte.
  5. catnon aspetterò revdi reindirizzare l'intero file. Inizierà semplicemente nel momento in cui arriva la prima parte delle informazioni, il che significa che, a seconda del simbolo utilizzato, aprirà una connessione file.txt.
  6. In questo caso, poiché hai usato > invece di >> , la shell troncerà il file di output, il che significa che aprirà e cancellerà le informazioni file.txtmentre attende che le nuove informazioni arrivino ad esso. Con >> aprirebbe una connessione file.txte attenderebbe nuove informazioni sull'ultima riga rilevata.
  7. Dato che le informazioni erano già state cancellate file.txtcon > , revavrebbero provato a farlo funzionare e non ottenere nulla perché catcancellato tutto in preparazione delle nuove informazioni.

Quindi perché gli altri funzionano dopo aver letto quanto sopra. A causa di ciò:

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

Qui stai eseguendo il piping su cat che sta inviando le informazioni a un altro file. In questo caso, il file di input elaborato file.txtnon è lo stesso del file di output file2.txt. Dopo di che stai letteralmente sovrascrivendo il tutto file2.txtcon file.txt, quindi tutto il processo fatto da è catstato eliminato. Fondamentalmente l'intera riga potrebbe essere semplificata come cp file.txt file2.txtperché sta facendo la stessa cosa poiché file2.txtalla fine perde la reve viene sovrascritta con il mvcomando.

rev file.txt | cat >> file.txt

In questo caso stai concatenando le informazioni nello stesso file. Quindi sta solo aprendo una connessione a quel file ma non sta cancellando le informazioni viste con un singolo > . Il risultato finale dovrebbe essere, l'informazione originale più l'informazione invertita.


5
Il file non viene troncato da cat. Viene troncato dalla shell, prima ancora che venga avviato uno qualsiasi dei comandi nella pipeline.
Emil Jeřábek,

Corretto, cercavo parole più facili da spiegare. Dal momento che è un po 'difficile spiegare se l'OP non sa che shell è e tutto il resto. Cercando di renderlo il più "amichevole" possibile.
Luis Alvarado,

1
Bene, non importa che sia fatto dalla shell, ma che i tempi che presenti sono sbagliati. Il troncamento non avverrà nel passaggio 6, ma nel passaggio 0. rev file.txt | cat --bogus-option > file.txtTroncerà anche il file, anche se cat non tenterà di aprirlo.
Emil Jeřábek, l'

@ EmilJeřábek hai ragione. Tuttavia, gli utenti che non sanno come si comporteranno saranno più facili se procediamo passo dopo passo con solo i comandi. Anche il tuo esempio sta ancora inviando le informazioni allo stesso file, quindi bash leggerà l'intera riga, vedrà l'output e continuerà ad aprirsi E troncarlo. L'errore è semplicemente lo stderr in uscita su stdout.
Luis Alvarado,

4
Vedi anche moreutils , una fantastica raccolta di strumenti (disponibile dal repository di pacchetti come moreutils) che include sponge, uno strumento appositamente progettato per la base di sovrascrittura di un file di input. Ad esempio, la rev file.txt >file2.txt && mv file2.txt file.txtsoluzione alternativa diventerebbe rev file.txt | sponge file.txt, che funzionerà correttamente anche quando c'è già qualcosa di nome file2.txt.
Daniel Wagner,

9

Quando la shell vede il reindirizzamento, apre prima i file pertinenti, prima di eseguire uno qualsiasi dei comandi coinvolti. Pertanto, quando lo fai:

foo file.txt | bar > file.txt

Il reindirizzamento per file.txtcausare il troncamento prima di foo essere eseguito e può essere letto file.txt. In una nota a margine, ecco perché non puoi fare:

sed 'blah' file.txt > file.txt

E perché sedha un'opzione di modifica sul posto.

Infine, facendo:

.. | cat > file.txt

è un uso inutile di cat , soprattutto se si sta tentando di leggere in file.txtprecedenza.

Se si desidera invertire un file sul posto, non ci sono scorciatoie . Potresti essere in grado di utilizzare i trucchi sedo awkcon la modifica sul posto.


3

>è un redirector (operatore) che invia l'output a qualcos'altro
(input del comando successivo, stampante ..)

Nel tuo caso l'output passa a un file file.txt, se questo file esiste già viene sovrascritto, in caso contrario viene creato.

>>è un operatore append, se file.txtesiste già l'output viene aggiunto alla fine del file. se il file non esiste, viene creato e l'output scritto nel nuovo file, lo stesso di >(redirector).


L'OP sembra averlo capito. La confusione sembra derivare solo dallo stesso file che si trova su entrambi i lati degli operatori >e >>.
bzlm,

0

Puoi usare Vim in modalità Ex:

ex -sc '%!rev' -cx file.txt
  1. % seleziona tutte le righe

  2. ! esegui comando

  3. x salva e chiudi

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.