¿Por qué el signo menos que no funciona como un reemplazo para cat in bash?

17

Escuché sobre el "uso inútil del gato" y encontré algunas sugerencias, pero lo siguiente no muestra nada en mi shell bash.

< filename

Sin embargo, usar cat funciona como se esperaba.

cat filename

Estoy usando Fedora Core 18 y GNU bash, versión 4.2.45 (1).

EDITAR: Usarlo delante de una tubería tampoco funciona.

< filename | grep pattern

Mientras que usar cat funciona como se esperaba.

cat filename | grep pattern

EDIT2: para aclarar, sé que puedo usar esto

grep pattern < filename

pero leí aquí /programming/11710552/useless-use-of-cat que también puedo usar delante del comando. Sin embargo, no funciona delante del comando.

error
fuente
2
Funciona. Lo que intentaste no es lo mismo que sugiere el comentario de Jonathan Leffler .
manatwork
"El propósito de cat es concatenar (o" catenate ") archivos. Si es solo un archivo, concatenarlo sin nada es una pérdida de tiempo y le cuesta un proceso". partmaps.org/era/unix/award.html
Bonsi Scott

Respuestas:

22

El símbolo menor que y ( <) abre el archivo y lo adjunta al controlador de dispositivo de entrada estándar de alguna aplicación / programa. Pero no le ha dado al shell ninguna aplicación para adjuntar la entrada.

Ejemplo

Estos 2 ejemplos hacen esencialmente lo mismo, pero obtienen su entrada de 2 maneras ligeramente diferentes.

abre archivo

$ cat blah.txt 
hi

abre STDIN

$ cat < blah.txt 
hi

Mirando detrás de la cortina

Puedes usar stracepara ver qué está pasando.

Cuando leemos de un archivo

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

Cuando leemos de STDIN (identificado como 0)

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

En el primer ejemplo, podemos ver que catabrió el archivo y leer de él, blah.txt. En el segundo podemos ver que catlee el contenido del archivo a blah.txttravés del descriptor de archivo STDIN, identificado como descriptor número 0.

read(0, "hi\n", 65536)                  = 3
slm
fuente
1
¿Entonces esta charla sobre el uso inútil del gato es falsa?
error
@bug: no, hay usos. Pero catgeneralmente se entiende mal y se usa cuando no es necesario.
slm
¿Pero es necesario cuando quiero preservar el orden de las operaciones de izquierda a derecha? Leí que también es posible usar la construcción menor que delante del comando.
error
@bug sí, la redirección puede ocurrir antes o después del comando, vea la respuesta de Stephane, también muestra este ejemplo.
slm
Ah, ahora lo entiendo. Tendría que escribir < filename command.
error
14

El uso inútil clásico cates cuando lo usas para dar entrada a programas que son perfectamente capaces de abrir archivos directamente. Por ejemplo:

Malo

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

Bueno

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

También es bueno ( <filepuede estar a ambos lados del comando)

<file grep foo
 sed 's/a/b/' < file
<file awk '{print $1}' 
terdon
fuente
66
"Malo" es subjetivo aquí. Creo que son mejores en general, porque es mucho más consistente y más fácil de leer. Y el flujo de datos es completamente de izquierda a derecha, como debería ser si hay más tuberías involucradas
Izkata
2
@Izkata son "malos" en el sentido de que son usos inútiles de cat.
terdon
"¡Abajo! ¡Sal de la mesa! Eres un mal gato! ";-) Pero en serio ...
G-Man dice 'reinstalar a Monica' el
1
Buena digno de mención (o, al menos, útiles) usos de la catincluyen (1) cat file(con salida a la pantalla / terminal; aunque, si el archivo es más largo que la pantalla es alta, es posible que prefiera utilizar moreo lesso algo por el estilo), (2) cat file1 file2 file3 > all_data( exactamente para qué catsirve), (3) cat f1 f2 f3 | tr …(o canalizar a cualquier otro programa al que no desee pasar los archivos directamente; por ejemplo, wc(por ejemplo, si desea ver el total general solamente) o grep(p. ej., si tiene una versión anterior que no es compatible -h, es decir, --no-filename)) ... (Cont.)
G-Man dice 'Reinstate Monica'
(Cont.) ... (4) cat -n file | sort … -k1 | sed 's/^ *[0-9]*\t//', (5) sudo cat file600 | untrusted_program(es decir, usted (su UID) no puede leer el archivo y no desea ejecutar el programa como root o incluso cualquier UID semi-privilegiado). Además, ( e ) (es decir, un número entre 2 y 3) program_that_generates_html | cat static_html_header - static_html_footer(que probablemente desee redirigir a un archivo o una tubería).
G-Man dice 'Restablecer a Monica' el
13

El UUOC está en:

cat somefile | some-cmd

o

cat < somefile | some-cmd

Allí, some-cmdestá leyendo el contenido de somefileuna tubería que se alimenta de la catcual él mismo lo lee somefile.

some-cmdpuede leer directamente desde somefile(después de que el shell lo haya abierto en stdin), no hay necesidad de cat:

some-cmd < somefile

o

< somefile some-cmd

(las redirecciones pueden aparecer en cualquier lugar en una línea de comando simple).

Stéphane Chazelas
fuente