2010-03-31 14 views
13

C'è un caso di ... o contesto in cui cat file | ... si comporta diversamente da ... <file?cat ... vs ... <file

+0

Se si chiede perché si vede una forma o l'altra utilizzata in luoghi diversi, sembra essere una questione di preferenze personali. Kernighan e Pike lo notarono nel 1984: http://www.amazon.com/Unix-Programming-Environment-Prentice-Hall-Software/dp/013937681X – msw

+1

Appartiene a superuser.com –

risposta

9

Durante la lettura da un file normale, cat è responsabile della lettura dei dati, esegue ciò che preferisce e potrebbe vincolarlo nel modo in cui lo scrive sulla pipeline. Ovviamente, i contenuti stessi sono conservati, ma qualsiasi altra cosa potrebbe essere contaminata. Ad esempio: dimensione del blocco e tempistica di arrivo dei dati. Inoltre, il tubo in sé non è sempre neutro: funge da buffer aggiuntivo tra l'input e ....

modo semplice e veloce per rendere la questione dimensione del blocco apparente:

$ cat large-file | pv >/dev/null 
5,44GB 0:00:14 [ 393MB/s] [    <=>         ] 
$ pv <large-file >/dev/null 
5,44GB 0:00:03 [1,72GB/s] [=================================>] 100% 
+1

Interessante, anche se dato che read() usa un buffer finito, in entrambi i casi si raggiungono dimensioni minime del buffer di alcuni processi. strace mostra che cat usa 32kB reads e pv 128kB sulla mia piattaforma. – msw

+0

Oh, ehi, il mio esempio in realtà non corrisponde alla domanda, dal momento che non sto usando

+0

@msw otterrà * molto * dipendente dall'implementazione di 'cat', ma proverò a renderlo evidente in un modo diverso. –

1

cat file | avvia un altro programma (cat) che non deve essere avviato nel secondo caso. Rende anche più confuso se si desidera utilizzare "documenti qui". Ma dovrebbe comportarsi allo stesso modo.

4

cat consente di collegare più file in sequenza. In caso contrario, il reindirizzamento < e cat file | producono gli stessi effetti collaterali.

2

Pipes causano una subshell per essere invocato per il comando a destra. Ciò interferisce con le variabili di ambiente.

cat foo | while read line 
do 
    ... 
done 
echo "$line" 

contro

while read line 
do 
    ... 
done < foo 
echo "$line" 
+0

Entrambi hanno dato gli stessi risultati quando li ho provati. –

+0

effetto collaterale interessante. – pra

+0

@JB: imposta una variabile all'interno del ciclo, quindi la fa eco dopo il ciclo. Il valore modificato persisterà solo dopo il modulo reindirizzato e non dopo il modulo inviato. Un'altra dimostrazione è 'cd' all'interno del ciclo e' pwd' dopo il ciclo. –

4

Oltre la cosa postato da altri utenti, quando si utilizza il reindirizzamento input da un file, lo standard input è il file, ma quando il piping dell'output del gatto con l'ingresso, in ingresso standard è un flusso con il contenuto del file. Quando l'input standard è il file sarà in grado di cercare all'interno del file ma il pipe non lo permetterà. Si può vedere questo trovando un file zip ed eseguire i seguenti comandi:

zipinfo /dev/stdin < thezipfile.zip 

e

cat thezipfile.zip | zipinfo /dev/stdin 

Il primo comando mostrerà il contenuto del file zip, mentre il secondo mostra un errore, anche se è un errore fuorviante perché zipinfo non controlla il risultato della chiamata di ricerca e gli errori in seguito.

3

A l'uso inutile di gatto è sempre da evitare. È come guidare con il freno a mano su. Spreca i cicli della CPU per niente, il sistema operativo costantemente cambia il passaggio tra il processo gatto e quello successivo nella pipe. Se tutti i gatti inutili del mondo se ne fossero andati e smesso di essere inventati, reinventati, trasmessi di padre in figlio, non avremmo il riscaldamento globale perché potremmo facilmente vivere con 1,21 Gigawatt di energia risparmiata.

Grazie. Mi sento meglio ora. Per favore unisciti a me nella mia crociata per eliminare l'uso inutile di cat su stackoverflow. Questo sito è, per quanto io lo percepisca, un importante contributo alla proliferazione di gatti inutili. Non do la colpa ai neofiti, ma voglio insegnarli. Lavoratori e neofiti del mondo, allenta il freno a mano e salva il pianeta !!! 1!

1

Un'ulteriore differenza è il comportamento su un blocco open() del file di input.

Per esempio, supponendo di ingresso è un FIFO senza scrittori, un'invocazione non deporrà le uova tutti i programmi per bambini fino a quando si apre il file di input, mentre l'altro si riproducono due processi:

prog ... < a_fifo  # 'prog' not launched until shell can open file 
cat a_fifo | prog ... # 'prog' and 'cat' are running (latter may block on open) 

In pratica questo raramente questioni tranne in circostanze artificiali. prog potrebbe eseguire periodicamente il log o eseguire alcuni lavori di pulizia durante l'attesa dell'input, ad esempio, che potrebbe verificarsi anche se nessun input è disponibile. (Perché lo prog non dovrebbe essere abbastanza sofisticato da aprire il proprio input fifo non bloccante?)