Pourquoi le signe inférieur à ne fonctionne-t-il pas en remplacement de cat in bash?

17

J'ai entendu parler de "l'utilisation inutile de chat" et j'ai trouvé quelques suggestions, mais ce qui suit ne produit rien dans mon shell bash.

< filename

Cependant, l'utilisation de cat fonctionne comme prévu.

cat filename

J'utilise Fedora Core 18 et GNU bash, version 4.2.45 (1).

EDIT: L'utiliser devant un tuyau ne fonctionne pas non plus.

< filename | grep pattern

Alors que l'utilisation de chat fonctionne comme prévu.

cat filename | grep pattern

EDIT2: Pour clarifier, je sais que je peux utiliser cette

grep pattern < filename

mais j'ai lu ici /programming/11710552/useless-use-of-cat que je peux également l'utiliser devant la commande. Cependant, cela ne fonctionne pas devant la commande.

punaise
la source
2
Ça marche. Ce que vous avez essayé n'est pas le même que le commentaire de Jonathan Leffler suggère.
manatwork
"Le but de cat est de concaténer (ou" caténater ") des fichiers. S'il ne s'agit que d'un seul fichier, le concaténer avec rien du tout est une perte de temps et vous coûte un processus." partmaps.org/era/unix/award.html
Bonsi Scott

Réponses:

22

Le symbole inférieur à et ( <) ouvre le fichier et le joint au descripteur de périphérique d'entrée standard d'une application / d'un programme. Mais vous n'avez donné au shell aucune application à laquelle attacher l'entrée.

Exemple

Ces 2 exemples font essentiellement la même chose mais obtiennent leur contribution de 2 manières légèrement différentes.

ouvre le fichier

$ cat blah.txt 
hi

ouvre STDIN

$ cat < blah.txt 
hi

Furtivement derrière le rideau

Vous pouvez utiliser stracepour voir ce qui se passe.

Quand on lit un fichier

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

Lorsque nous lisons dans STDIN (identifié comme 0)

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

Dans le premier exemple, nous pouvons voir que catle fichier a été ouvert et lu à partir de celui-ci blah.txt,. Dans la seconde, nous pouvons voir que catlit le contenu du fichier blah.txtvia le descripteur de fichier STDIN, identifié comme le descripteur numéro 0.

read(0, "hi\n", 65536)                  = 3
slm
la source
1
Donc, ce discours sur l'utilisation inutile du chat est faux?
bug
@bug - non, il y a des utilisations. Mais catest généralement mal compris et utilisé lorsqu'il n'est pas nécessaire.
slm
Mais faut-il quand je veux conserver l'ordre des opérations de gauche à droite? J'ai lu qu'il est également possible d'utiliser la construction inférieure à devant la commande.
bug
@bug oui la redirection peut se produire avant ou après la commande, voir la réponse de Stéphane, il montre également cet exemple.
slm
Ah, maintenant je comprends. Il faudrait que j'écrive < filename command.
bug
14

L'utilisation inutile classique de catest lorsque vous l'utilisez pour donner une entrée à des programmes qui sont parfaitement capables d'ouvrir des fichiers directement. Par exemple:

Mal

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

Bien

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

Aussi bon (le <filepeut être de chaque côté de la commande)

<file grep foo
 sed 's/a/b/' < file
<file awk '{print $1}' 
terdon
la source
6
"Mauvais" est subjectif ici. Je trouve que c'est mieux dans l'ensemble, car c'est beaucoup plus cohérent et plus facile à lire. Et le flux de données est entièrement de gauche à droite, comme il se doit s'il y a plus de tuyaux impliqués
Izkata
2
@Izkata, ils sont "mauvais" dans le sens où ils sont des utilisations inutiles cat.
terdon
"Vers le bas! Descendez de la table! Tu es un mauvais chat! ”;-) Mais sérieusement…
G-Man dit 'Réintègre Monica' le
1
Bonnes utilisations notables (ou, au moins, utiles) de catinclude (1) cat file(avec sortie vers l'écran / le terminal; bien que, si le fichier est plus long que l'écran est haut, vous préférerez peut-être utiliser moreou lessou quelque chose comme ça), (2) cat file1 file2 file3 > all_data( exactement à quoi cela catsert), (3) cat f1 f2 f3 | tr …(ou dirigez-vous vers tout autre programme auquel vous ne voulez pas transmettre directement les fichiers; par exemple, wc(par exemple, si vous voulez voir le grand total uniquement) ou grep(par exemple, si vous avez une ancienne version qui ne prend pas en charge -h, c.-à-d. --no-filename)),… (suite)
G-Man dit «Reinstate Monica»
(Suite)… (4) cat -n file | sort … -k1 | sed 's/^ *[0-9]*\t//', (5) sudo cat file600 | untrusted_program(c'est-à-dire que vous (votre UID) ne pouvez pas lire le fichier, et vous ne voulez pas exécuter le programme en tant que root ou même n'importe quel UID semi-privilégié). Aussi, ( e ) (c'est-à-dire un nombre entre 2 et 3) program_that_generates_html | cat static_html_header - static_html_footer(que vous voudriez probablement rediriger vers un fichier ou un canal).
G-Man dit `` Réintègre Monica '' le
13

L'UUOC est en:

cat somefile | some-cmd

ou

cat < somefile | some-cmd

Là, some-cmdest la lecture du contenu de somefilepartir d' un tuyau qui est alimenté par catqui se lit à partir somefile.

some-cmdpeut lire directement depuis somefile(après que le shell l'ait ouvert sur stdin), il n'est pas nécessaire de cat:

some-cmd < somefile

ou

< somefile some-cmd

(les redirections peuvent apparaître n'importe où sur une simple ligne de commande).

Stéphane Chazelas
la source