Dlaczego znak „mniej niż” nie działa jako zamiennik kota w bash?

17

Słyszałem o „bezużytecznym użyciu kota” i znalazłem kilka sugestii, ale poniższe nie dają nic w mojej powłoce bash.

< filename

Używanie kota działa zgodnie z oczekiwaniami.

cat filename

Używam Fedory Core 18 i GNU bash, wersja 4.2.45 (1).

EDYCJA: Używanie go przed rurą też nie działa.

< filename | grep pattern

Natomiast użycie kota działa zgodnie z oczekiwaniami.

cat filename | grep pattern

EDYCJA 2: Aby to wyjaśnić, wiem, że mogę tego użyć

grep pattern < filename

ale przeczytałem tutaj /programming/11710552/useless-use-of-cat, że mogę go również użyć przed poleceniem. Nie działa to jednak przed poleceniem.

pluskwa
źródło
2
To działa. To, czego próbowałeś, nie jest tym samym, co sugeruje komentarz Jonathana Lefflera .
manatwork,
„Celem cat jest łączenie plików (lub„ catenate ”). Jeśli jest to tylko jeden plik, łączenie go z niczym nie jest stratą czasu i kosztuje proces”. partmaps.org/era/unix/award.html
Bonsi Scott

Odpowiedzi:

22

Symbol mniej niż i ( <) otwiera plik i dołącza go do standardowego uchwytu urządzenia wejściowego jakiejś aplikacji / programu. Ale nie dałeś powłoce żadnej aplikacji, do której mógłbyś dołączyć dane wejściowe.

Przykład

Te 2 przykłady robią w zasadzie to samo, ale wkładają je w 2 nieco odmienne sposoby.

otwiera plik

$ cat blah.txt 
hi

otwiera STDIN

$ cat < blah.txt 
hi

Zaglądając za zasłonę

Możesz użyć, straceaby zobaczyć, co się dzieje.

Kiedy czytamy z pliku

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

Kiedy czytamy ze STDIN (oznaczonego jako 0)

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

W pierwszym przykładzie widzimy, że catotworzył plik i odczytał z niego blah.txt,. W drugim widzimy, że catczyta zawartość pliku blah.txtza pomocą deskryptora pliku STDIN, oznaczonego jako deskryptor numer 0.

read(0, "hi\n", 65536)                  = 3
slm
źródło
1
Czyli ta rozmowa o bezużytecznym użyciu kota jest fałszywa?
błąd
@bug - nie, są zastosowania. Ale catjest ogólnie źle rozumiany i używany, gdy nie jest to konieczne.
slm
Ale jest to konieczne, gdy chcę zachować porządek operacji od lewej do prawej? Przeczytałem, że przed poleceniem można również użyć mniej niż konstruktu.
błąd
@bug tak przekierowanie może nastąpić przed poleceniem lub po nim, zobacz odpowiedź Stephane'a, pokazuje również ten przykład.
slm
Ach, teraz rozumiem. Musiałbym pisać < filename command.
błąd
14

Klasyczne bezużyteczne użycie cat polega na tym, że używa się go do wprowadzania programów, które doskonale potrafią bezpośrednio otwierać pliki. Na przykład:

Zły

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

Dobry

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

Również dobrze ( <filemoże być po obu stronach polecenia)

<file grep foo
 sed 's/a/b/' < file
<file awk '{print $1}' 
terdon
źródło
6
„Zły” jest tutaj subiektywny. Uważam, że są one ogólnie lepsze, ponieważ są o wiele bardziej spójne i łatwiejsze do odczytania. A przepływ danych jest całkowicie od lewej do prawej, tak jak powinno być, jeśli w
grę wchodzi
2
@Izkata są „złe” w tym sensie, że są bezużyteczne cat.
terdon
"Na dół! Zejdź ze stołu! Jesteś złym kotem! ”;-) Ale poważnie…
G-Man mówi„ Przywróć Monikę ”
1
Na uwagę zasługuje dobra (lub przynajmniej przydatne) zastosowania catobejmują (1) cat file(z wyjściem na ekran / terminala, chociaż, jeśli plik jest dłuższa niż ekran jest wysoka, może wolisz używać morelub lessczy coś takiego) (2) cat file1 file2 file3 > all_data( dokładnie do czego catsłuży), (3) cat f1 f2 f3 | tr …(lub potokuj do innego programu, do którego nie chcesz przekazywać plików bezpośrednio; np. wc(Np. Jeśli chcesz zobaczyć tylko sumę całkowitą) lub grep(np. jeśli masz starą wersję, która nie obsługuje -h, tj. --no-filename)),… (ciąg dalszy)
G-Man mówi „Przywróć Monikę”
(Ciąg dalszy)… (4) cat -n file | sort … -k1 | sed 's/^ *[0-9]*\t//', (5) sudo cat file600 | untrusted_program(tzn. Ty (twój UID) nie możesz odczytać pliku i nie chcesz uruchamiać programu jako root lub nawet częściowo uprzywilejowany UID). Również ( e ) (tj. Liczba od 2 do 3) program_that_generates_html | cat static_html_header - static_html_footer(którą prawdopodobnie chciałbyś przekierować do pliku lub potoku).
G-Man mówi „Reinstate Monica”
13

UUOC znajduje się w:

cat somefile | some-cmd

lub

cat < somefile | some-cmd

Tam some-cmdczyta zawartość somefilerury, która jest zasilana przez catktórą sama ją odczytuje somefile.

some-cmdmoże czytać bezpośrednio z somefile(po tym, jak powłoka otworzy go dla standardowego wejścia), nie ma potrzeby cat:

some-cmd < somefile

lub

< somefile some-cmd

(przekierowania mogą pojawiać się w dowolnym miejscu w prostym wierszu poleceń).

Stéphane Chazelas
źródło