Perché il segno di meno di non funziona in sostituzione di cat in bash?


17

Ho sentito parlare di "uso inutile di gatto" e ho trovato alcuni suggerimenti, ma i seguenti risultati non hanno prodotto nulla nella mia shell bash.

< filename

L'uso di cat funziona come previsto però.

cat filename

Sto usando Fedora Core 18 e GNU bash, versione 4.2.45 (1).

EDIT: anche usarlo davanti a una pipe non funziona.

< filename | grep pattern

Considerando che l'utilizzo di cat funziona come previsto.

cat filename | grep pattern

EDIT2: Per chiarire, so che posso usare questo

grep pattern < filename

ma ho letto qui /programming/11710552/useless-use-of-cat che posso anche usarlo davanti al comando. Tuttavia, non funziona di fronte al comando.


2
Funziona. Proprio quello che hai provato non è lo stesso suggerito dal commento di Jonathan Leffler .
arte

"Lo scopo di cat è concatenare (o" catenare ") i file. Se si tratta di un solo file, concatenarlo con nulla è una perdita di tempo e ti costa un processo." partmaps.org/era/unix/award.html
Bonsi Scott,

Risposte:


22

Il simbolo minore di e ( <) sta aprendo il file e allegandolo all'handle del dispositivo di input standard di alcune applicazioni / programmi. Ma non hai fornito alla shell alcuna applicazione a cui allegare l'input.

Esempio

Questi 2 esempi fanno essenzialmente la stessa cosa ma ottengono il loro contributo in 2 maniere leggermente diverse.

apre il file

$ cat blah.txt 
hi

apre STDIN

$ cat < blah.txt 
hi

Sbirciando dietro il sipario

Puoi usare straceper vedere cosa sta succedendo.

Quando leggiamo da un file

open("blah.txt", O_RDONLY)              = 3
fstat(3, {st_mode=S_IFREG|0664, st_size=3, ...}) = 0
fadvise64(3, 0, 0, POSIX_FADV_SEQUENTIAL) = 0
read(3, "hi\n", 65536)                  = 3
write(1, "hi\n", 3hi
)                     = 3
read(3, "", 65536)                      = 0
close(3)                                = 0
close(1)                                = 0

Quando leggiamo da STDIN (identificato come 0)

read(0, "hi\n", 65536)                  = 3
write(1, "hi\n", 3hi
)                     = 3
read(0, "", 65536)                      = 0
close(0)                                = 0
close(1)                                = 0

Nel primo esempio possiamo vedere che ha cataperto il file e letto da esso blah.txt,. Nel secondo possiamo vedere che catlegge il contenuto del file blah.txttramite il descrittore di file STDIN, identificato come descrittore numero 0.

read(0, "hi\n", 65536)                  = 3

1
Quindi questo discorso sull'uso inutile del gatto è falso?
bug,

@bug - no, ci sono usi. Ma catè generalmente frainteso e viene utilizzato quando non è necessario.
slm

Ma è necessario quando voglio preservare l'ordine delle operazioni da sinistra a destra? Ho letto che è possibile usare anche il costrutto less-than davanti al comando.
bug,

@bug sì, il reindirizzamento può avvenire prima o dopo il comando, vedi la risposta di Stephane, mostra anche questo esempio.
slm

Ah, ora capisco. Dovrei scrivere < filename command.
bug,

14

Il classico uso inutile di catè quando lo si utilizza per fornire input a programmi perfettamente in grado di aprire direttamente i file. Per esempio:

Cattivo

cat file | grep foo
cat file | while read line; do echo "$line"; done
cat file | sed 's/a/b/'
cat file | awk '{print $1}'

Buona

grep foo file
while read line; do echo "$line"; done < file 
sed 's/a/b/' file
awk '{print $1}' file

Anche buono ( <filepuò essere su entrambi i lati del comando)

<file grep foo
 sed 's/a/b/' < file
<file awk '{print $1}' 

6
"Bad" è soggettivo qui. Trovo che siano complessivamente migliori, perché è molto più coerente e più facile da leggere. E il flusso di dati è completamente da sinistra a destra, come dovrebbe essere se ci fossero più pipe coinvolte
Izkata,

2
@Izkata sono "cattivi", nel senso che sono usi inutili cat.
terdon

"Giù! Esci dal tavolo! Sei un brutto gatto! ";-) Ma seriamente ...
G-Man dice" Ripristina Monica "il

1
Buono degno di nota (o, almeno, utili) usi di catincludono (1) cat file(con output a schermo / terminale, anche se, se il file è più lungo dello schermo è elevata, si potrebbe preferisce utilizzare moreo lesso qualcosa di simile), (2) cat file1 file2 file3 > all_data( esattamente a cosa catserve), (3) cat f1 f2 f3 | tr …(o pipe in qualsiasi altro programma a cui non si desidera passare direttamente i file; ad esempio, wc(ad esempio, se si desidera vedere solo il totale generale) o grep(ad esempio, se hai una versione precedente che non supporta -h, ad es. --no-filename)), ... (proseguendo)
G-Man dice "Reinstate Monica" il

(Continua) ... (4) cat -n file | sort … -k1 | sed 's/^ *[0-9]*\t//', (5) sudo cat file600 | untrusted_program(ovvero, tu (il tuo UID) non puoi leggere il file e non vuoi eseguire il programma come root o anche con un UID semi-privilegiato). Inoltre, ( e ) (cioè un numero compreso tra 2 e 3) program_that_generates_html | cat static_html_header - static_html_footer(che probabilmente vorresti reindirizzare a un file o una pipe).
G-Man dice "Ripristina Monica" il

13

L'UUOC è in:

cat somefile | some-cmd

o

cat < somefile | some-cmd

Lì, some-cmdsta leggendo il contenuto di somefileuna pipa che è alimentata da catcui essa stessa lo legge somefile.

some-cmdpuò leggere direttamente da somefile(dopo che la shell lo ha aperto su stdin), non è necessario cat:

some-cmd < somefile

o

< somefile some-cmd

(i reindirizzamenti possono apparire ovunque su una semplice riga di comando).

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.