Почему не работает подстановка команд и конвейер [дубликат]

Я практикую | конвейер для передачи вывода.

Во-первых, я пробую следующую командную строку,

$ basename -a $(ls test_directory/*) 

Эта строка работает как моя цель, которая показывает только имя файла без имени каталога.

Но следующая команда не сработала

$ ls test_directory/* | basename -a

Сообщение об ошибке здесь:

basename: missing operand
Try 'basename --help' for more information.

Я нашел такую ​​страницу, относящуюся к моему вопросу.

Передайте вывод предыдущей команды следующей в качестве аргумента

1.Передача ввода с помощью stdin:

ls | wc -l Это будет подсчитывать строки в выводе ls

2. Передача ввода с помощью аргументов командной строки:

wc -l $ (ls) Это будет подсчитывать строки в списке файлов, напечатанных ls

Я не могу понять разницу между «выводом ls» и «файлами, напечатанными ls». Разве это не одно и то же? Я хочу понять разницу.

И я хочу понять, почему моя пробная командная строка, "$ ls td / * | базовое имя -a" не работает.

Я хочу получить совет.
Спасибо за внимание.

1
задан 11 August 2020 в 05:44

2 ответа

Чтобы объяснить разницу между ls | wc -l и wc -l $ (ls) . Приведу пример.

1. ls | wc -l

Как упоминалось в сообщении, эта команда будет подсчитывать строки в выводе "ls"

Например, у меня есть каталог ~ / Desktop / Practice / python , который содержит 4 сценария Python.
Теперь, если я использую указанную выше команду, я получаю следующий результат:

4

Это означает, что wc -l подсчитывает вывод команды ls , которая вернула 4 сценария Python, следовательно count стало 4

2. wc -l $ (ls)

Опять же, как было предложено в сообщении, эта команда будет подсчитывать строки в списке файлов, напечатанных "ls".
Поскольку в этом случае вы передаете «ls» в качестве аргумента команды

Теперь, если я использую указанную выше команду в том же каталоге, я получаю следующий результат:

12 palindrome1.py
11 palindrome2.py
12 palindrome3.py
6 palindrome4.py
Всего 41

Это показывает, что wc -l на этот раз подсчитал количество строк, присутствующих в каждом отдельном скрипте Python, который был возвращен ему ls .

Разница b / w аргумент командной строки и стандартный ввод

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

Канал передает стандартный вывод одной команды второй команде в качестве стандартного ввода. Следовательно, если вторая команда не может обработать стандартный ввод, она выдаст ошибку. Однако некоторые команды принимают как аргументы командной строки, так и стандартный ввод, например «wc», но результат отличается, поскольку «wc» по-разному обрабатывает стандартный ввод и аргументы командной строки.

В вашем случае это было базовое имя . Если вы читаете справочную страницу basename:

NAME
       basename - strip directory and suffix from filenames

SYNOPSIS
       basename NAME [SUFFIX]
       basename OPTION... NAME...

DESCRIPTION
       Print NAME with any leading directory components removed.  If specified, also remove a trailing SUFFIX.

       Mandatory arguments to long options are mandatory for short options too.

       -a, --multiple
              support multiple arguments and treat each as a NAME

Здесь четко указано, что basename принимает аргументы командной строки для ввода. Следовательно, труба не будет работать.

Как заставить работать трубу

Как было предложено @ bac0n для выполнения "basename" с конвейером, вам необходимо использовать "xargs".
ls | xargs basename -a

Это работает, потому что xargs принимает стандартный ввод и передает другой команде как «аргумент командной строки».

Надеюсь, это проясняет ваш вопрос.

3
ответ дан 11 August 2020 в 20:06

Самый простой способ продемонстрировать это:

enter image description here

Некоторые команды созданы для приема stdin . Возьмем для примера кот . Вы можете направить вывод команды предварительного просмотра на cat :

$ echo hi | cat

Некоторые команды получают только аргументы в качестве входных данных, например echo . Если вы запустите:

$ ls | echo

, он направит вывод ls в echo . Но echo его не получит. Чтобы использовать echo , вы должны указать ему несколько аргументов:

$ echo "I'm an argument"

Если вам нужно использовать вывод команды в качестве аргумента для какой-либо другой команды (например, в случае, когда она принимает только аргументы, а не ] stdin ), у вас есть разные варианты. Один из них - использовать подстановку команд:

$ echo $(ls)

В этом случае ls будет запущен, тогда вывод ls будет передан в качестве аргументов echo .

То же самое для basename . Вы должны передавать аргументы.

Также есть команды, которые могут принимать аргумент и stdin одновременно. Например кот . Если вы отправите что-то в cat , он распечатает это. Однако для аргумента необходимо передать имя файла , чтобы распечатать его содержимое.

1
ответ дан 11 August 2020 в 20:06

Другие вопросы по тегам:

Похожие вопросы: