Почему оболочка автоматически не исправляет «бесполезное использование кошки»? [закрыто]

28

Многие люди используют oneliners и скрипты, содержащие код вдоль строк

cat "$MYFILE" | command1 | command2 > "$OUTPUT"

Первый catчасто называют «бесполезным использованием кошки», потому что технически это требует запуска нового процесса (часто /usr/bin/cat), где этого можно избежать, если команда была

< "$MYFILE" command1 | command2 > "$OUTPUT"

потому что тогда нужно только запустить оболочку command1и просто указать ее stdinна данный файл.

Почему оболочка не выполняет это преобразование автоматически? Я чувствую, что синтаксис «бесполезного использования кота» легче читать, и оболочка должна иметь достаточно информации, чтобы автоматически избавиться от бесполезного кота. Это catопределено в стандарте POSIX, поэтому оболочке следует разрешить реализовать его внутри, а не использовать двоичный файл в пути. Оболочка может даже содержать реализацию только для одной версии аргумента и возврата к двоичному в пути.

Микко Ранталайнен
источник
22
Эти команды на самом деле не эквивалентны, так как в одном случае stdin - это файл, а в другом - труба, поэтому это не будет строго безопасное преобразование. Вы могли бы сделать систему, которая сделала это, хотя.
Майкл Гомер
14
То, что вы не можете представить себе вариант использования, не означает, что приложению не разрешено бесполезно полагаться на указанное поведение. Получение ошибки lseekпо-прежнему является определенным поведением и может привести к другому результату, другое поведение блокировки может быть семантически значимым и т. Д. Было бы допустимо внести изменения, если бы вы знали, что были другие команды, и знали, что им все равно, или если вы просто не заботитесь о совместимости на этом уровне, но выгода довольно мала. Я предполагаю, что отсутствие выгоды ведет к ситуации больше, чем стоимость соответствия.
Майкл Гомер
3
Оболочке абсолютно разрешено реализовывать catсебя, правда, или любую другую утилиту. Также разрешено знать, как работают другие утилиты, принадлежащие системе (например, он может знать, как ведет себя внешняя grepреализация , поставляемая с системой ). Это вполне жизнеспособно, поэтому справедливо задаться вопросом, почему они этого не делают.
Майкл Гомер
6
@MichaelHomer Например, он может знать, как ведет себя внешняя реализация grep, поставляемая с системой, поэтому оболочка теперь зависит от поведения grep. И sed. И awk. И du. А сколько сотен, если не тысяч других утилит?
Эндрю Хенле
19
Было бы довольно не круто из моей оболочки редактировать мои команды для меня.
Азор Ахай

Ответы:

25

2 команды не эквивалентны: рассмотрим обработку ошибок:

cat <file that doesn't exist> | less создаст пустой поток, который будет передан в конвейерную программу ... как таковой, вы получите отображение, ничего не показывающее.

< <file that doesn't exist> less не удастся открыть бар, а затем не открыть вообще.

Попытка заменить первое на второе может сломать любое количество сценариев, которые ожидают запуска программы с потенциально пустым вводом.

UKMonkey
источник
1
Я отмечу ваш ответ как принятый, потому что я считаю, что это самое важное различие между обоими синтаксисами. Вариант с catвсегда будет выполнять вторую команду в конвейере, тогда как вариант с простым перенаправлением ввода вообще не будет выполнять команду, если входной файл отсутствует.
Микко Ранталайнен
Однако обратите внимание, что <"missing-file" grep foo | echo 2не будет выполняться, grepно будет выполняться echo.
Микко Ранталайнен
51

«Бесполезное использование cat» - это больше о том, как вы пишете свой код, чем о том, что на самом деле выполняется при выполнении скрипта. Это своего рода анти-шаблонный дизайн , способ сделать что-то, что, вероятно, можно сделать более эффективным способом. Это ошибка в понимании того, как наилучшим образом комбинировать данные инструменты для создания нового инструмента. Я бы сказал, что объединение нескольких sedи / или awkкоманд в конвейер также иногда можно назвать признаком того же самого анти-паттерна.

Исправление случаев «бесполезного использования cat» в скрипте - это, прежде всего, вопрос ручного исправления исходного кода скрипта. Инструмент, такой как ShellCheck, может помочь с этим, указав на очевидные случаи:

$ cat script.sh
#!/bin/sh
cat file | cat
$ shellcheck script.sh

In script.sh line 2:
cat file | cat
    ^-- SC2002: Useless cat. Consider 'cmd < file | ..' or 'cmd file | ..' instead.

Заставить оболочку делать это автоматически было бы сложно из-за природы сценариев оболочки. Способ выполнения сценария зависит от среды, унаследованной от его родительского процесса, и от конкретной реализации доступных внешних команд.

Оболочка не обязательно знает, что catесть. Это может быть любая команда из любого места $PATHили функция.

Если бы это была встроенная команда (которая может быть в некоторых оболочках), она могла бы реорганизовать конвейер так, как она знала бы семантику своей встроенной catкоманды. Прежде чем сделать это, он должен был бы дополнительно сделать предположения о следующей команде в конвейере, после оригинальной cat.

Обратите внимание, что чтение из стандартного ввода ведет себя немного иначе, когда он подключен к каналу и когда он подключен к файлу. Канал не является доступным для поиска, поэтому в зависимости от того, что делает следующая команда в конвейере, он может или не может вести себя по-разному, если конвейер был переставлен (он может определить, является ли ввод доступным для поиска, и решить, что делать по-другому, если он есть или если это не так, в любом случае это будет вести себя иначе).

Этот вопрос похож (в очень общем смысле) на « Существуют ли какие-либо компиляторы, которые пытаются исправить синтаксические ошибки самостоятельно? » (На сайте Software Engineering StackExchange), хотя этот вопрос, очевидно, касается синтаксических ошибок, а не бесполезных шаблонов проектирования. , Идея автоматического изменения кода, основанного на намерениях, во многом совпадает.

Кусалананда
источник
Для оболочки вполне соответствует то, что catесть, и другие команды в конвейере (правило «как будто») и ведут себя соответственно, их здесь просто нет, потому что это бессмысленно и слишком сложно.
Майкл Гомер
4
@MichaelHomer Да. Но также допускается перегрузка стандартной команды с функцией с тем же именем.
Кусалананда
2
@PhilipCouling Это абсолютно соответствует, пока известно, что ни одна из команд конвейера не заботится. Оболочке специально разрешено заменять служебные программы встроенными функциями или функциями оболочки, которые не имеют ограничений среды выполнения, поэтому внешний результат неразличим, он разрешен. Для вашего случая, cat /dev/ttyэто интересный, который будет отличаться <.
Майкл Гомер
1
@MichaelHomer, так что пока внешний результат неразличим, он разрешен. Это означает, что поведение всего набора утилит, оптимизированных таким образом, никогда не изменится . Это должно быть адом окончательной зависимости.
Эндрю Хенле
3
@MichaelHomer Как уже говорилось в других комментариях, оболочка, безусловно, знает, что, учитывая ввод OP, невозможно сказать, что на catсамом деле делает команда, не выполнив ее . Все, что вы (и оболочка) знаете, у ОП есть на catсвоем пути команда, представляющая собой интерактивную имитацию кота, «myfile» - это просто сохраненное состояние игры, command1и command2они обрабатывают некоторую статистику о текущем игровом сеансе ...
алефзеро
34

Потому что это не бесполезно.

В случае cat file | cmd, fd 0(stdin) cmdбудет труба, а в случае cmd <fileэто может быть обычный файл, устройство и т. Д.

Канал имеет семантику, отличную от обычного файла, и его семантика не является подмножеством семантики обычного файла:

  • обычный файл нельзя select(2)редактировать или poll(2)редактировать осмысленным образом; select(2)на нем всегда будет возвращать «готов». Расширенные интерфейсы, такие как epoll(2)в Linux, просто не будут работать с обычными файлами.

  • на Linux есть системные вызовы ( splice(2), vmsplice(2), tee(2)) , которые только работа на трубах [1]

Поскольку catон используется очень часто, его можно реализовать как встроенную оболочку, которая позволит избежать лишнего процесса, но как только вы начнете работать по этому пути, то же самое можно будет сделать с большинством команд - преобразовать оболочку в более медленную и более медленную. perlили python. вероятно, лучше написать другой язык сценариев с простым в использовании конвейерным синтаксисом для продолжения ;-)

[1] Если вы хотите, чтобы простой пример не был скомпонован по этому случаю, вы можете взглянуть на мой git gist "exec binary from stdin" с некоторыми пояснениями в комментарии здесь . Реализация catвнутри него для того, чтобы он работал без UUoC, увеличил бы его в 2 или 3 раза.

mosvy
источник
2
На самом деле, ksh93 делает выполнение некоторых внешних команд , как catвнутренне.
jrw32982 поддерживает Монику
3
cat /dev/urandom | cpu_bound_programзапускает read()системные вызовы в отдельном процессе. Например, в Linux фактическая работа ЦП по генерированию большего количества случайных чисел (когда пул пуст) выполняется в этом системном вызове, поэтому использование отдельного процесса позволяет использовать преимущество отдельного ядра ЦП для генерации случайных данных в качестве входных данных. Например, в разделе Какой самый быстрый способ создания текстового файла размером 1 ГБ, содержащего случайные цифры?
Питер Кордес
4
Что более важно для большинства случаев, это означает, lseekчто не будет работать. cat foo.mp4 | mpv -будет работать, но вы не можете искать в обратном направлении дальше, чем кеш-буфер mpv или mplayer. Но с вводом, перенаправленным из файла, вы можете. cat | mpv -это один из способов проверить, имеет ли MP4 свой moovатом в начале файла, поэтому его можно воспроизводить без поиска конца и назад (т. е. подходит ли он для потоковой передачи). Легко представить другие случаи, когда вы хотите протестировать программу на наличие файлов без возможности поиска, запустив ее /dev/stdinс catперенаправлением.
Питер Кордес
Это еще более верно при использовании xargs cat | somecmd. Если пути к файлам выходят за пределы ограничения буфера команд, они xargsмогут запускаться catнесколько раз, что приводит к непрерывному потоку, в то время как xargs somecmdпрямое использование часто приводит к сбою, потому что somecmdне может быть выполнено в несколько раз для достижения плавного результата.
Tasket
17

Потому что обнаружить бесполезного кота действительно очень сложно.

У меня был сценарий оболочки, где я написал

cat | (somecommand <<!
...
/proc/self/fd/3
...
!) 0<&3

Сценарий оболочки завершился неудачно, если catбыл удален, потому что он был вызван с помощью su -c 'script.sh' someuser. По-видимому, излишняя catпричина в том, что владелец стандартного ввода сменил пользователя, на котором выполнялся сценарий, чтобы снова открыть его через /proc.

Джошуа
источник
Этот случай будет довольно простым, поскольку он явно не следует простой модели, за которой catследует ровно один параметр, поэтому оболочка должна использовать реальный catисполняемый файл вместо оптимизированного ярлыка. Хороший вопрос о возможных других учетных данных или нестандартном стандартном вводе данных для реальных процессов.
Микко Ранталайнен
13

tl; dr: оболочки не делают этого автоматически, потому что затраты превышают вероятные выгоды.

Другие ответы указывают на техническое различие между stdin, являющимся каналом, и файлом. Учитывая это, оболочка может выполнить одно из следующих действий:

  1. Реализуйте catкак встроенную, сохраняя при этом различие между файлом и каналом. Это позволило бы сэкономить на затратах и, возможно, вилке.
  2. Выполните полный анализ конвейера со знанием различных команд, используемых для определения, имеет ли значение файл / канал, а затем действуйте на основе этого.

Далее вы должны рассмотреть затраты и преимущества каждого подхода. Преимущества достаточно просты:

  1. В любом случае, избегайте exec (of cat)
  2. Во втором случае, когда возможна подмена с перенаправлением, следует избегать разветвления.
  3. В тех случаях , когда вы должны использовать трубу, это может быть возможно иногда , чтобы избежать вилочный / vfork, но часто нет. Это потому, что эквивалент для кошки должен работать одновременно с остальной частью конвейера.

Таким образом, вы экономите немного процессорного времени и памяти, особенно если вы можете избежать форка. Конечно, вы экономите это время и память только тогда, когда эта функция действительно используется. И вы только экономите время на форк / exec; для больших файлов это время ввода-вывода (например, cat читает файл с диска). Поэтому вы должны спросить: как часто cat(бесполезно) используется в сценариях оболочки, где производительность действительно имеет значение? Сравните это с другими обычными встроенными оболочками, такими как test- трудно представить, что catон используется (бесполезно) даже на десятую часть от того, что testиспользуется в местах, которые имеют значение. Это предположение, я не измерил, это то, что вы хотели бы сделать перед любой попыткой реализации. (Или аналогичным образом, попросив кого-то еще реализовать, например, запрос функции).

Далее вы спросите: каковы расходы. На ум приходят две затраты: (а) дополнительный код в оболочке, который увеличивает его размер (и, следовательно, возможно, использует память), требует больше работы по обслуживанию, является еще одним местом для ошибок и т. Д .; и (b) неожиданности обратной совместимости, POSIX catпропускает множество функций, например, GNU coreutils cat, поэтому вам нужно быть осторожным в точности, что бы catвстроенная программа реализовала.

  1. Дополнительная встроенная опция, вероятно, не так уж и плоха - добавление еще одной встроенной функции, в которой группа уже существует. Если у вас есть данные профилирования, показывающие, что это поможет, вы, вероятно, можете убедить авторов вашей любимой оболочки добавить их.

  2. Что касается анализа конвейера, я не думаю, что оболочки делают что-то подобное в настоящее время (некоторые распознают конец конвейера и могут избежать разветвления). По сути, вы бы добавили (примитивный) оптимизатор в оболочку; оптимизаторы часто оказываются сложным кодом и источником множества ошибок. И эти ошибки могут вызывать удивление - небольшие изменения в сценарии оболочки могут привести к тому, что вы избежите или вызовете ошибку.

Постскриптум: Вы можете применить подобный анализ к вашим бесполезным использованиям кошек. Преимущества: легче читать (хотя, если command1 примет файл в качестве аргумента, вероятно, нет). Затраты: дополнительная ветвь и exec (и если команда1 может принять файл в качестве аргумента, возможно, более запутанные сообщения об ошибках). Если ваш анализ говорит вам бесполезно использовать кошку, тогда продолжайте.

derobert
источник
10

catКоманда может принять в -качестве маркеров для стандартного ввода . ( POSIX , « Если файл является '-', утилита cat должна читать из стандартного ввода в этой точке последовательности. ") Это позволяет легко обрабатывать файл или стандартный ввод, если в противном случае это было бы запрещено.

Рассмотрим эти два тривиальных альтернативы, где аргумент оболочки $1является -:

cat "$1" | nl    # Works completely transparently
nl < "$1"        # Fails with 'bash: -: No such file or directory'

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

file="$1"
reader=cat
[[ $file =~ \.gz$ ]] && reader=zcat
[[ $file =~ \.bz2$ ]] && reader=bzcat
"$reader" "$file"

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

cat file.txt

В любой другой ситуации сами по catсебе могут потребоваться.

roaima
источник
6

Команда cat может делать то, что оболочка не может делать (или, по крайней мере, не может делать легко). Например, предположим, что вы хотите напечатать символы, которые в противном случае могли бы быть невидимыми, такие как вкладки, возврат каретки или перевод строки. Может быть, * есть * способ сделать это только с помощью встроенных команд оболочки, но я не могу думать ни о чем из головы. GNU-версия cat может сделать это с -Aаргументом или -v -E -Tаргументами (хотя я не знаю о других версиях cat). Вы также можете использовать префикс каждой строки с помощью номера строки -n(опять же, IDK, если версии не-GNU могут это делать).

Еще одним преимуществом кошки является то, что она может легко читать несколько файлов. Для этого можно просто напечатать cat file1 file2 file3. Чтобы сделать то же самое с оболочкой, все будет сложно, хотя тщательно продуманная петля, скорее всего, может достичь того же результата. Тем не менее, вы действительно хотите потратить время на написание такого цикла, когда существует такая простая альтернатива? Я не!

Чтение файлов с помощью cat, вероятно, потребляет меньше ресурсов ЦП, чем оболочка, поскольку cat является предварительно скомпилированной программой (очевидное исключение составляет любая оболочка со встроенным cat). При чтении большой группы файлов это может стать очевидным, но я никогда не делал этого на своих машинах, поэтому не уверен.

Команда cat также может быть полезна для принуждения команды к принятию стандартного ввода в тех случаях, когда это не так. Учтите следующее:

echo 8 | sleep

Число «8» не будет принято командой «sleep», так как оно никогда не предназначалось для приема стандартного ввода. Таким образом, сон будет игнорировать этот ввод, жаловаться на отсутствие аргументов и выход. Однако, если один печатает:

echo 8 | sleep $(cat)

Многие оболочки расширят это до sleep 8, и сон будет ждать 8 секунд перед выходом. Вы также можете сделать что-то подобное с ssh:

command | ssh 1.2.3.4 'cat >> example-file'

Эта команда с добавлением файла примера на машине с адресом 1.2.3.4 с любым выводом из «команды».

И это (вероятно) просто царапает поверхность. Я уверен, что мог бы найти больше примеров того, как кошка может быть полезна, если бы захотел, но этот пост достаточно длинный. Итак, в заключение я скажу следующее: попросить оболочку предвидеть все эти сценарии (и несколько других) не реально.

TSJNachos117
источник
Я бы закончил последнее предложение словами «это нелегко»
Василий Старинкевич
3

Помните, что у пользователя может быть catсвой, $PATHкоторый не совсем POSIX cat(но, возможно, какой-то вариант, который может что-то регистрировать). В этом случае вы не хотите, чтобы оболочка удаляла его.

Они PATH могут динамически меняться, и тогда cat это не то, во что вы верите. Было бы довольно сложно написать оболочку для оптимизации, о которой вы мечтаете.

Также на практике cat это довольно быстрая программа. Есть несколько практических причин (кроме эстетики), чтобы избежать этого.

См. Также прекрасную речь об анализе POSIX [s] Яна Регина-Джианаса на FOSDEM2018. Это дает другие веские причины избегать попыток делать то, о чем вы мечтаете, в оболочке.

Если бы производительность действительно была проблемой для оболочек, кто-то предложил бы оболочку, которая использует сложные методы оптимизации всего компилятора программы, статический анализ исходного кода и методы компиляции точно в срок (все эти три области имеют десятилетия прогресса и научных публикаций и посвящены конференции, например, под SIGPLAN ). К сожалению, даже как интересная тема исследования, которая в настоящее время не финансируется исследовательскими агентствами или венчурными капиталистами, и я полагаю, что это просто не стоит усилий. Другими словами, вероятно, нет значительного рынка для оптимизации оболочек . Если у вас есть полмиллиона евро на такие исследования, вы легко найдете кого-то, кто будет этим заниматься, и я считаю, что это даст достойные результаты.

С практической стороны, переписывая, чтобы улучшить свою производительность, обычно делается небольшой (не сто строк) сценарий оболочки на любом лучшем языке сценариев (Python, AWK, Guile, ...). И нецелесообразно (по многим причинам разработки программного обеспечения) писать большие сценарии оболочки: когда вы пишете сценарий оболочки длиной более ста строк, вам нужно подумать о перезаписи его (даже для удобства чтения и обслуживания) на более подходящем языке : как язык программирования оболочка очень плохая. Однако существует много больших сгенерированных сценариев оболочки, и по веским причинам (например, сгенерированные configureсценарии GNU autoconf ).

Что касается огромных текстовых файлов, передача их catв качестве одного аргумента не является хорошей практикой, и большинство системных администраторов знают это (когда запуск любого сценария оболочки занимает больше минуты, вы начинаете рассматривать его оптимизацию). Для больших гигабайты файлов, catне является и не инструмент хорошо их обработать.

Василий Старынкевич
источник
3
«Практически мало практических причин, чтобы избежать этого» - любой, кто ждал, cat some-huge-log | tail -n 5чтобы бежать (где он tail -n 5 some-huge-logмог прыгнуть прямо до конца, тогда как catчитает только спереди назад), не согласится.
Чарльз Даффи
Комментарий проверяет ^ catбольшой текстовый файл размером в десятки ГБ (который был создан для тестирования) занимает довольно много времени. Не рекомендую.
Сергей Колодяжный
1
Кстати, «нет значительного рынка для оптимизации оболочек» - ksh93 - это оптимизирующая оболочка, и довольно хорошая. Некоторое время он был успешно продан в качестве коммерческого продукта. (К сожалению, коммерческая лицензия также сделала достаточно нишу, что плохо написанные клоны и другие менее способные, но бесплатные наследники захватили мир за пределами тех сайтов, которые готовы платить за лицензию, что приводит к ситуации, которую мы иметь сегодня).
Чарльз Даффи
(не используя конкретные методы, которые вы отмечаете, но, честно говоря, эти методы не имеют смысла, учитывая модель процесса; методы, которые она применяет, хорошо, хорошо применяются и дают хороший эффект ).
Чарльз Даффи
2

Если добавить ответ @Kusalananda (и комментарий @alephzero), cat может быть чем угодно:

alias cat='gcc -c'
cat "$MYFILE" | command1 | command2 > "$OUTPUT"

или

echo 'echo 1' > /usr/bin/cat
cat "$MYFILE" | command1 | command2 > "$OUTPUT"

Нет никаких причин, по которым cat (сам по себе) или / usr / bin / cat в системе на самом деле является инструментом объединения cat.

обкрадывать
источник
3
Кроме того, поведение catопределяется POSIX и поэтому не должно сильно отличаться.
Роайма
2
@roaima: PATH=/home/Joshua/bin:$PATH cat ...Вы уверены, что знаете, что catделает сейчас?
Джошуа
1
@ Джошуа, это не имеет значения. Мы оба знаем, что catих можно переопределить, но мы оба знаем, что их не следует произвольно заменять чем-то другим. Мой комментарий указывает на то, что POSIX требует определенного (подмножества) поведения, которое можно разумно ожидать. Иногда я писал сценарий оболочки, который расширяет поведение стандартной утилиты. В этом случае сценарий оболочки действовал и вел себя так же, как инструмент, который он заменил, за исключением того, что он имел дополнительные возможности.
Роайма
@Joshua: на большинстве платформ оболочки знают (или могут знать), какие каталоги содержат исполняемые файлы, которые реализуют команды POSIX. Таким образом , вы могли бы просто отложить до замещения после расширения псевдонима и разрешения пути, и делать это только для /bin/cat. (И вы бы сделали эту опцию, которую вы могли бы отключить.) Или вы бы сделали catвстроенную оболочку (которая может /bin/catиспользовать несколько аргументов?), Чтобы пользователи могли контролировать, хотят ли они внешнюю версию нормальной Кстати, с enable cat. Как для kill. (Я думал, что bash command catбудет работать, но это не пропускает встроенные функции)
Питер Кордес
Если вы предоставите псевдоним, оболочка будет знать, что catв этой среде больше не ссылается на обычную cat. Очевидно, что оптимизация должна быть реализована после обработки псевдонимов. Я считаю встроенные оболочки для представления команд в виртуальном каталоге, который всегда предшествует вашему пути. Если вы хотите избежать встроенной в оболочку версии какой-либо команды (например test), вы должны использовать вариант с путем.
Микко Ранталайнен
1

Два «бесполезных» использования для кошки:

sort file.txt | cat header.txt - footer.txt | less

... здесь catиспользуется для смешивания ввода файлов и каналов.

find . -name '*.info' -type f | sh -c 'xargs cat' | sort

... здесь xargsможно принимать практически бесконечное количество имен файлов и запускать catстолько раз, сколько необходимо, при этом все они ведут себя как один поток. Так что это работает для больших списков файлов, где прямое использование xargs sortне.

Tasket
источник
Оба этих варианта использования можно было бы избежать, если встроить в оболочку только step-in, если catвызывается только с одним аргументом. Особенно в случае, когда shпередается строка и xargsбудет вызываться catнапрямую, оболочка не сможет использовать свою встроенную реализацию.
Микко Ранталайнен
0

Помимо прочего, cat-check добавит дополнительные потери производительности и путаницу относительно того, какое использование на catсамом деле бесполезно, IMHO, потому что такие проверки могут быть неэффективными и создавать проблемы с законным catиспользованием.

Когда команды имеют дело со стандартными потоками, им нужно заботиться только о чтении / записи в стандартные файловые дескрипторы. Команды могут знать, является ли stdin доступным для поиска / доступным или нет, что указывает на канал или файл.

Если мы добавим к проверке, какой процесс на самом деле предоставляет содержимое стандартного ввода, нам нужно будет найти процесс на другой стороне канала и применить соответствующую оптимизацию. Это можно сделать с точки зрения самой оболочки, как показано в сообщении SuperUser Кайла Джонса, и с точки зрения оболочки, это

(find /proc -type l | xargs ls -l | fgrep 'pipe:[20043922]') 2>/dev/null

как показано в связанном посте. Это еще 3 команды (поэтому дополнительные fork()s и exec()s) и рекурсивные обходы (так много readdir()вызовов).

С точки зрения C и исходного кода оболочки, оболочка уже знает дочерний процесс, поэтому нет необходимости в рекурсии, но как мы узнаем, когда оптимизировать, а когда catна самом деле бесполезно? Есть на самом деле полезные использования кошки , такие как

# adding header and footer to file
( cmd; cat file; cmd ) | cmd
# tr command does not accept files as arguments
cat log1 log2 log3 | tr '[:upper:]' '[:lower:]'

Вероятно, было бы бесполезно и бесполезно добавлять такую ​​оптимизацию в оболочку. Как уже упоминалось в ответе Кусаланды, UUOC больше относится к отсутствию у пользователя понимания того, как наилучшим образом комбинировать команды для достижения наилучших результатов.

Сергей Колодяжный
источник