Перенаправление содержимого файла на команду «эхо»

41

У меня есть файл с именем my_file.txt, содержимое которого является просто строкой Hello. Как я мог перенаправить его содержимое в команду echo?

Я знаю , что есть команды less, cat, more... но мне нужно сделать это с echo.

Я попробовал это:

$ cat my_file.txt | echo

а также это:

$ echo < my_file.txt

Но в обоих случаях в stdout отображается только пробел, а не содержимое my_file.txt.

Как я мог это сделать?

danielmbcn
источник
7
Почему вы настаиваете на использовании echo?
Кевин
7
@Kevin, по-видимому, в конечном итоге он хочет развернуть escape-последовательности ANSI C ( \n, b...) в файле, что будет допустимым использованием echo(по крайней мере, стандартным echo). Или, по-видимому, он хочет понять, почему это не работает таким образом. В любом случае, нет причин понижать рейтинг ИМО.
Стефан Шазелас
3
Я пришел сюда, потому что мне было любопытно, почему это не работает, когда я делаю echo <file.txt. Кажется, разумный вопрос для SE, ответ был очень полезным. +1 от меня.
нейронет

Ответы:

53

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

Если вы хотите echoотобразить содержимое файла, вы должны передать это содержимое в качестве аргумента echo. Что-то типа:

echo "$(cat my_file.txt)"

Обратите внимание , что $(...)полосы тянущейся символ новой строки с с выхода этой catкоманды, и echoдобавляет одну задние.

Также обратите внимание, что кроме как zsh, вы не можете передавать NUL-символы в аргументах команды, так что описанное выше обычно не работает с двоичными файлами. yashтакже удалит байты, которые не являются частью допустимых символов.

Если причина для желания сделать это потому , что вы хотите , echoчтобы расширить \n, \b, \0351... экранирующие последовательности в файле (в UNIX совместимые echoреализации делают, но не все ), то вы бы лучше использовать printfвместо :

printf '%b\n' "$(cat my_file.txt)"

В отличие от echoэтого, он является переносимым и не будет иметь проблем, если содержимое файла начинается с -.


В качестве альтернативы $(cat file), с ksh, zshи bash, можно также сделать:$(<file) . Это специальный оператор, в котором оболочка вместо catсодержимого читает файл для расширения. Он по-прежнему удаляет завершающие символы новой строки и заглушает байты NUL, кроме как в zsh. В том bash, что все еще разветвляется дополнительный процесс. Также обратите внимание, что одно отличие состоит в том, что вы не получите никакой ошибки, если попытаетесь прочитать файл типа directory таким образом. Кроме того, хотя он $(< file)является особенным, $(< file; other command)это не так ( zshесли не эмулировать другую оболочку, это все равно расширило бы содержимое file, выполнив неявную $READNULLCMD команду (обычно это пейджер)).

Стефан Шазелас
источник
3
В обоих Баш и ЗШ вы можете пропустить catи просто оболочка читать непосредственно: echo "$(<my_file.txt)".
Кевин
1
Да, с ksh , zsh и bash вы можете использовать $(<filename).
Димитр Радулов
Большое спасибо, это то, что мне было нужно, и это сработало! :-)
danielmbcn
@Kevin, Dimitre, добавлено сейчас.
Стефан
4

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

echo $(<my_file.txt)

или

echo `<my_file.txt`

$()и `` выполняют то же самое, они запускают команды внутри своей области видимости и передают вывод в оболочку, как если бы он был задан как ввод пользователем. Единственное различие между ними состоит в том, что $ () может быть рекурсивным и `` не может быть рекурсивным.

GypsyCosmonaut
источник
2

Простой ответ: вы не можете. echo(будь то встроенная оболочка или обычный двоичный файл) не обрабатывает свой стандартный ввод - это только один способ.

peterph
источник
Вопрос в том, почему вы действительно хотите это сделать?
Петер
2

Как было сказано,

Если вы хотите echoотобразить содержимое файла, вы должны передать его в качестве аргументаecho

Например, вы можете сделать это следующим образом xargs(учитывая, что вам нужно включить интерпретацию обратной косой черты ):

$ cat my_file.txt | xargs echo -e

Или просто то, что вы спросили (без интерпретации последовательностей Escape ):

$ cat my_file.txt | xargs echo
Kenichi
источник
Однако обратите внимание, что при использовании xargs echo(то же самое, что и xargsbtw как echoкоманда по умолчанию) echoбудет выполняться команда из файловой системы, а не встроенная echoкоманда оболочки . Также обратите внимание, что xargsожидается его ввод в очень специфическом формате (где пробелы, новые строки, кавычки, обратные слеши имеют особое значение). catздесь не имеет особого смысла, так как есть только один файл для объединения (так же, как < file.txt xargs echo. Обратите внимание, что Unix-совместимые echos по умолчанию выполняют экранирование с обратной косой чертой и выводят их -eпри этом echo -e.
Стефан
0

В bash также должно работать следующее:

echo `cat my_file.txt`

Часть в обратных галочках заменяется выводом этой команды, т.е. в этом случае заменяется содержимым файла.

Motlib
источник
Правда, галочки работают как $( . . . ). Люди, которые используют, $()обычно предпочитают их, потому что вы можете их вкладывать. Этот вопрос старый, но гораздо приятнее отвечать на вопросы, на которые еще нет ответа!
Закон 29
Не совсем. Есть небольшая разница. Когда используется обратная галочка, обратный слеш сохраняет свое буквальное значение, за исключением случаев, когда следует $, `или \. Первая обратная галочка, которой не предшествует обратная косая черта, завершает команду. При использовании формы $ (,,,) все символы в скобках составляют команду.
fpmurphy
Поскольку эта подстановка команд не заключена в кавычки, к ней будет применен оператор split + glob. Например, если my_file.txtсодержит *, это напечатало бы список имен файлов в текущем каталоге.
Стефан