Почему знак «меньше» не работает вместо кошки в bash?

17

Я слышал о «бесполезном использовании кошки» и нашел некоторые предложения, но следующие ничего не выводят в моей оболочке bash.

< filename

Использование кошки работает, как и ожидалось.

cat filename

Я использую Fedora Core 18 и GNU bash, версия 4.2.45 (1).

РЕДАКТИРОВАТЬ: Использование его перед трубой тоже не работает.

< filename | grep pattern

Принимая во внимание, что использование кошки работает как ожидалось.

cat filename | grep pattern

EDIT2: чтобы уточнить, я знаю, что я могу использовать это

grep pattern < filename

но я прочитал здесь /programming/11710552/useless-use-of-cat, что я также могу использовать его перед командой. Это не работает перед командой, хотя.

ошибка
источник
2
Оно работает. То, что вы попробовали, не то же самое, что предполагает комментарий Джонатана Леффлера .
manatwork
«Цель cat состоит в том, чтобы объединять (или« объединять ») файлы. Если это всего лишь один файл, объединение его вообще ни с чем - пустая трата времени и стоит вам процесс». partmaps.org/era/unix/award.html
Бонси Скотт

Ответы:

22

Символ less than и ( <) открывает файл и присоединяет его к стандартному дескриптору устройства ввода некоторого приложения / программы. Но вы не дали оболочке ни одного приложения для присоединения ввода.

пример

Эти 2 примера, по сути, делают то же самое, но получают свой вклад в 2 слегка отличающихся способа.

открывает файл

$ cat blah.txt 
hi

открывает STDIN

$ cat < blah.txt 
hi

Заглядывать за занавес

Вы можете использовать, straceчтобы увидеть, что происходит.

Когда мы читаем из файла

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

Когда мы читаем из STDIN (идентифицируется как 0)

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

В первом примере мы видим, что catоткрыли файл и прочитали из него blah.txt,. Во втором мы видим, что catсодержимое файла считывается blah.txtчерез дескриптор файла STDIN, идентифицируемый как дескриптор номер 0.

read(0, "hi\n", 65536)                  = 3
SLM
источник
1
Значит, этот разговор о бесполезном использовании кошки является фальшивкой?
ошибка
@bug - нет, есть использование. Но, catкак правило, неправильно понимается и используется, когда в этом нет необходимости.
SLM
Но это необходимо, когда я хочу сохранить порядок операций слева направо? Я читал, что перед командой также можно использовать конструкцию «меньше».
ошибка
@bug да, перенаправление может произойти до или после команды, см. ответ Стефана, он также показывает этот пример.
SLM
Ах, теперь я понял. Я должен был написать < filename command.
ошибка
14

Классическое бесполезное использование cat- это когда вы используете его для ввода программ, которые способны открывать файлы напрямую. Например:

Плохо

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

Хорошо

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

Также хорошо ( <fileможет быть на любой стороне команды)

<file grep foo
 sed 's/a/b/' < file
<file awk '{print $1}' 
Тердон
источник
6
«Плохо» здесь субъективно. Я считаю , тем лучше в целом, потому что это путь более последовательной и легче читать. И поток данных полностью слева направо, как и должно быть, если задействовано больше каналов
Изката
2
@Izkata они "плохие" в том смысле, что они бесполезны cat.
Тердон
"Вниз! Сойти со стола! Ты плохой кот! ”;-) А если серьезно…
G-Man говорит:« Восстановите Монику »
1
Обращает на себя внимание хорошо (или, по крайней мере, полезные) применения catвключают (1) cat file(с выходом на экран / терминал, хотя, если файл больше , чем экран высок, вы можете предпочесть использовать moreили lessили что - то в этом роде), (2) cat file1 file2 file3 > all_data( именно то , что catпредназначено), (3) cat f1 f2 f3 | tr …(или передать в любую другую программу, в которую вы не хотите передавать файлы напрямую, например wc(например, если вы хотите видеть только общий итог) или grep(например, если у вас есть старая версия, которая не поддерживает -h, т. е., --no-filename)),… (продолжение)
G-Man говорит: «Восстановите Монику»
(Продолжение)… (4) cat -n file | sort … -k1 | sed 's/^ *[0-9]*\t//', (5) sudo cat file600 | untrusted_program(т. Е. Вы (ваш UID) не можете прочитать файл, и вы не хотите запускать программу от имени пользователя root или даже с каким-либо полу привилегированным UID). Также, ( e ) (то есть число от 2 до 3) program_that_generates_html | cat static_html_header - static_html_footer(которое вы, вероятно, захотите перенаправить в файл или канал).
G-Man говорит: «Восстановите Монику»
13

UUOC находится в:

cat somefile | some-cmd

или

cat < somefile | some-cmd

Там some-cmdчитает содержимое somefileиз канала, по catкоторому он сам читает somefile.

some-cmdможет читать напрямую из somefile(после того, как оболочка открыла его для него на stdin), нет необходимости cat:

some-cmd < somefile

или

< somefile some-cmd

(перенаправления могут появляться в любом месте простой командной строки).

Стефан Шазелас
источник