Я хотел бы объединить вывод из echo с содержимым файла. Я попробовал следующую команду:
echo "abc" | cat 1.txt > 2.txt
но файл 2.txt
содержит только содержимое из 1.txt
. Почему это не работает?
Я хотел бы объединить вывод из echo с содержимым файла. Я попробовал следующую команду:
echo "abc" | cat 1.txt > 2.txt
но файл 2.txt
содержит только содержимое из 1.txt
. Почему это не работает?
Это не работает, потому что программе cat
в вашей последовательности каналов не было дано указание прочитать вывод программы echo
со стандартного ввода.
Вы можете использовать -
как псевдо-имя файла, чтобы указать стандартный ввод для cat
.
От man cat
на установку msys2:
EXAMPLES
cat f - g
Output f's contents, then standard input, then g's contents.
Так что постарайтесь
echo "abc" | cat - 1.txt > 2.txt
вместо.
Как отмечали другие, ваша оригинальная команда не работает, потому что cat 1.txt
игнорирует ее стандартный ввод. Либо укажите, что это должен быть его первый аргумент (cat - 1.txt
), либо используйте перенаправление блоков для перенаправления echo abc
и cat 1.txt
вместе. Для остроумия:
{ echo abc; cat 1.txt; } > 2.txt
Соответствующая выдержка из руководства (man bash
):
Составные команды
Составная команда является одной из следующих. В большинстве случаев список в описании команды может быть отделен от остальной части команды одним или несколькими символами новой строки и может сопровождаться символом новой строки вместо точки с запятой.
(
список)
Список выполняется в среде оболочки (см. ниже КОМАНДА ИСПОЛНИТЕЛЬНОЙ СРЕДЫ). Переменные и встроенные команды, которые влияют на среду оболочки, не остаются в силе после ее завершения. Статус возврата - это статус выхода из списка.
{
список;
}
Список просто выполняется в текущей среде оболочки. список должен заканчиваться символом новой строки или точкой с запятой. Это известно как групповая команда. Статус возврата - это статус выхода из списка. Обратите внимание, что в отличие от метасимволов
(
и)
,{
и}
являются зарезервированными словами и должны встречаться там, где зарезервированное слово разрешено распознавать. Поскольку они не вызывают разрыв слова, они должны быть отделены от списка пробелами или другими метасимволами оболочки.
Первый вариант (среда subshell) имеет множество побочных эффектов, большинство из которых, если не все, не имеют отношения к вашему сценарию; однако, если все, что вам нужно, - это перенаправить вывод нескольких команд, то здесь предпочтителен вариант № 2 (групповая команда).
( echo "abc"; cat 1.txt ) > 2.txt
Вы передали вывод эха в cat, но cat не использовал ввод и проигнорировали его. Теперь команды выполняются одна за другой, и их выходные данные группируются (круглые скобки) и направляются в 2.txt.
Ваша команда cat 1.txt
ничего не делает с выводом echo "abc"
.
Вместо этого:(echo "abc"; cat 1.txt) > 2.txt
запишет вывод обеих команд в 2.txt.
В любой оболочке POSIX вы можете использовать подстановку команд, чтобы использовать cat file
качестве входных данных для echo
:
echo $(cat file1.txt) "This Too"
В Bash вы можете использовать подстановку процессов и использовать echo в качестве другого "файла" для cat
, как в:
cat file1.txt <(echo This Too)
а затем направьте или перенаправьте вывод, как считаете нужным.
Как и в любом другом ответе, cat игнорирует стандартный ввод, если у него есть файл для просмотра. (Мне тоже нравятся ответы Даниэля и mvw, +1 за них)
Следующий код также будет работать:
echo abc >> 1.txt && cat 1.txt > 2.txt
Вывод echo abc будет добавлен в 1.txt с помощью >>. После этого && скажет ему выполнить следующий набор команд, который будет cat 1.txt, а затем выведет его в 2.txt. По сути, он добавляет вывод первой команды в 1.txt, а затем отправляет вывод 1.txt в 2.txt.
Если вы хотите, чтобы abc появлялся первым, вы можете использовать следующий код:
echo abc >> 2.txt && cat 1.txt >> 2.txt
Просто предположение, но похоже, что у вас есть повторяемый процесс, который является хорошим кандидатом на псевдоним или функцию. Псевдонимы - это, как правило, короткие пути для вызова команд bash, таких как аббревиатура, в одном входном потоке в качестве аргумента / ов.
alias hg="history | grep"
Однако в этом случае функция будет более читабельной, поскольку вы объединяете несколько дискретных (2) входных потоков, а также несколько команд bash. У вас есть два аргумента, первый - строка, а другой - путь к файлу. В конце вы хотите, чтобы результат был записан в поток вывода stdout.
В командной строке CLI введите это:
# ecat()
{
echo ${1}
cat ${2}
}
Ваша функция называется ecat, которая запоминается.
Теперь вы можете ссылаться как
ecat "abc" 1.txt
Чтобы добавить, просто укажите другое назначение вывода для stdout:
ecat "abc" 1.txt >> 2.txt
Оператор перенаправления добавления '>>' добавит вывод в конец указанного файла.
Если вам это нравится, добавьте файл ~/.bashrc для повторного использования.
declare -f ecat >> ~/.bashrc
Это также означает, что вы можете декорировать и т.д. В пределах определения вашей функции.
Также хорошая идея защитить файлы от перезаписи, добавив это в ваш ~/.bashrc
set noclobber