Я хотел бы перенаправить содержимое файла на ls
ввод команды:
ls -l < /home/john/1.txt
где 1.txt
содержание просто:
/etc
Я ожидал ls
перечислить содержимое файла, определенного в /home/jonh1.txt
- то есть /etc
dir, но, похоже, он игнорирует входной поток - по-прежнему перечисляет содержимое текущего каталога вместо /etc
dir, определенного в /home/jonh1.txt
file.
решение1
похоже, он игнорирует входной поток
Да. ls
Программаникогдаиспользует входной поток, потому что он не был написан для чтения чего-либо из входного потока. Это не то, что автоматически поставляется с любой программой Unix — это должно быть реализовано отдельно.
Не путайте поток ввода (stdin) с аргументами командной строки (argv); первый — это фактический поток, который можно читать построчно, а второй — это простой массив слов, доступный только для чтения. В вашем случае присутствуют оба и содержат разные данные.
(Почему бы этому не быть автоматическим для всех программ? Ну, возьмитеСортироватьиликотилигрэпв качестве примера. Эти программы принимают различные типы значений – имена файлов в качестве аргументов, но текст в качестве содержимого stdin. Таким образом, вы можете передать любую команду в | sort
, и она отсортирует ввод. Но если бы stdin и command-line были одним и тем же, вы | sort
больше ничего не могли бы передать в , потому что она бы думала, что ввод по каналу – это список имен файлов. Или наоборот, вы не могли бы дать ей имена файлов, потому что она просто отсортировала бы имена.)
Для альтернативного взгляда см.это объяснение на StackOverflow(о чем вы уже написали в комментариях).
решение2
Попробуйте использовать xargs:
xargs ls -l < /home/john/1.txt
решение3
Если вы напишете любую программу командной строки, которая принимает ввод от пользователя, вы очень ясно увидите, что происходит. Если в программе есть оператор read/readLine (в разных языках он может называться по-разному), то программа запрашивает у пользователя ввод, то вы также можете передать или перенаправить этот ввод с помощью |
или<
Если вы посмотрите на программу, которая принимает входные данные, вы увидите что-то вроде with more
или less
, если вы введете ее без входных данных $more<ENTER>
, то она запросит ввод. Передавая ей данные по конвейеру, она прекращает запрашивать ввод. Если мы запустим sed без параметров, $sed<ENTER>
то, конечно, она выдаст ошибку, и мы не сможем сделать ни $echo abc|sed<ENTER>
то, ни другое. Но если мы это сделаем $sed 's/a/b/'<ENTER>
, то она запросит ввод. И вот почему это echo abc|sed 's/a/b/'<ENTER>
работает.
Вы можете увидеть это, если напишете даже такую простую программу, как Hello World, но которая принимает ввод, как будто программа запрашивает слово, и если человек вводит «abc», она говорит «Hello abc». Вы сможете передать по конвейеру в эту программу. Не требуется никакого дополнительного программирования, чтобы заставить работать конвейер и перенаправление ввода. Если программа принимает ввод с клавиатуры от пользователя, то конвейер и перенаправление к ней будут работать, и тогда программа не будет запрашивать ввод.
решение4
Редактировать
Как отметил Камиль Мациоровски в комментарии ниже, следующий путь — неправильный.
Если
/home/john/1.txt
гарантированно содержит ровно один путь, товам определенно следует использовать двойные кавычки. Если файл может содержать более одного пути и вы намеренно полагаетесь на разбиение слов, то это неправильный способ предоставления произвольных путей.
Оригинальный пост (плохой пример)
Вы можете использовать следующее:
ls -l $(cat /home/john/1.txt)
См. > man bash
разделЗамена команды.