почему нельзя передать аргумент пути к файлу командной оболочки 'more' в режиме конвейера? - PullRequest
0 голосов
/ 16 октября 2019

У меня есть текстовый файл a.txt

hello world

Я использую следующие команды:

cmd1:

$ more a.txt
output:

hello world

cmd2:

$ echo 'a.txt'|more
output:

a.txt

Я думал, что cmd2 должен быть равен echo 'a.txt'|xargs -i more {} ,, но это не так.

Я хочу знать, почему cmd2 работает так и как писать код, который работает по-другому в режиме конвейера.

1 Ответ

1 голос
/ 16 октября 2019

Перенаправление с | или < контролирует что содержит поток stdin ;это не влияет на список аргументов командной строки программы.

Таким образом, more <a.txt (эффективно) или cat a.txt | more (неэффективно) оба прикрепляют дескриптор файла, из которого можно прочитать содержимое a.txt вдескриптор файла stdin нового процесса перед заменой этого процесса на more. Точно так же echo a.txt | more делает a.txt сам буквальный текст , который more читает из его потока stdin, , который является местом по умолчанию, в котором задокументировано получение входных данных для отображения, если не заданолюбые более конкретные имена файлов в командной строке .


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

Рассмотрим следующее, которое (использование NUL вместо разделителей новой строки для разделения имен файлов) является безопасным использованиемиз xargs, чтобы взять список имен файлов, передаваемых по нему, и преобразовать его в список аргументов в cat, используемый для объединения всех этих файлов вместе и генерирования одного потока ввода в more:

printf '%s\0' a.txt b.txt |
  xargs -0 cat -- |
  more
...