
Я уже некоторое время борюсь с этой проблемой и был бы очень признателен, если бы кто-нибудь мог мне ее прояснить. Предположим, я пытаюсь объединить две команды. readlink
иcat
readlink Command output
$ readlink -f SUService.log
/cygdrive/c/SUService.log
Теперь, если я попробую что-то подобное (не получится)
$ readlink -f SUService.log | cat
Хотя что-то вроде этого будет работать
$ readlink -f SUService.log | xargs cat
Я хотел узнать, почему это так? Я прочиталэтотпост здесь, в котором у ОП был похожий вопрос иэтотпост, который пытается объяснить разницу между аргументом и вводом, однако я все еще не могу уложить в голове принятый ответ(ы). Насколько я понимаю, это readlink
возвращает результат в stdout, который является экраном терминала, в то время как cat
хочет ввод в качестве аргумента. Это в свою очередь побуждает меня спросить, как мне узнать, может ли вывод команды (например, locate или readlink) работать как аргумент или нет для следующей команды? Я больше читал, и оказалось, что я хотел бы знать, когда мне следует использовать команду xarg?
решение1
Ваш пример довольно запутан.
Обычно вы не отправляете в cat просто так символы.
Обычно вы отправляете файл в cat.
Тем не менее, когда вы отправляете какие-либо символы в cat, он их выводит.
$ echo abc12123 | cat
abc12123
Обычно вы отправляете имя файла в cat
$ cat abc12123
cat: abc12123: No such file or directory
Обратите внимание, что сам cat по-разному обращается с забавными персонажами, переданными ему по конвейеру, и с теми, которые передаются ему в качестве параметра.
$ cat b.b
textofb.b
$ echo b.b | cat
b.b
$ cat b.b
textofb.b
Я буду использовать более простой пример, чем ваш.
$ echo b.b | xargs cat
textofb.b
см., он выводит содержимое bb, поскольку asdfasdfs | xargs cat
, отправит вывод asdfasdfs в качестве параметра в cat.
Так
echo b.b | xargs cat
=
cat b.b
В то время как echo b.b | cat
это не то же самое, чтоcat b.b
решение2
Следующая команда делаетнетфейл. Он просто делает то, чего вы не ожидали:
readlink -f SUService.log | cat
Когда cat
задан stdin, он копирует его в stdout. Он не ищет в нем имена файлов.
В качестве альтернативы будет выполнено чтение из указанного файла:
cat "$(readlink -f SUService.log)"
xargs
также поместит имя в cat
командную строку, что даст тот же результат:
readlink -f SUService.log | xargs cat
решение3
Взгляните на страницы руководства по cat и xargs, чтобы узнать, что они делают.
man cat
cat - concatenate files and print on the standard output
И:
man xargs
xargs - build and execute command lines from standard input
Вот небольшая демонстрация
Создадим тестовый файл:
echo "a" > test
echo "b" >> test
echo "c" >> test
кот
cat test
Читает файл и выдает:
a
b
c
эхо | кот
echo test | cat
Согласно man cat
, это делает то же самое, что:
echo test | cat -
Который передается test
в stdin кошки и сообщает ей, что нужно читать из stdin.
эхо | xargs кот
echo test | xargs cat
Генерирует и выполняет следующую команду:
cat test
Результат этого мы уже показали.
Если мы побежим
<test xargs -n1 cat
Xargs видит это при вводе:
a
b
c
И он генерирует следующие команды:
cat a
cat b
cat c
Что должно привести к трем ошибкам, поскольку эти файлы не существуют.
Почему -n1
?
Согласно man xargs
, -n1
xargs указывает использовать один аргумент (считанный из stdin) в каждой генерируемой им команде.
Если вместо этого мы используем -n2
, то сгенерируем следующее, в котором используется до двух параметров на команду:
cat a b
cat c
А если мы используем -n3
или выше, или просто опускаем -n
:
< test xargs cat
Мы получаем:
cat a b c