Вопрос по command-line, unix, utilities, prepend – Unix команда для добавления текста в файл

89

Есть ли команда Unix для добавления некоторых строковых данных в текстовый файл?

Что-то вроде:

prepend "to be prepended" text.txt
Если вы объедините все ответы, это, вероятно, самый компактный способ:<<(echo "to be prepended") < text.txt | sponge text.txt Sridhar-Sarnobat
Вы ищете одну команду, или небольшая команда сценария / псевдонима в порядке? Levon

Ваш Ответ

17   ответов
0
# create a file with content..
echo foo > /tmp/foo
# prepend a line containing "jim" to the file
sed -i "1s/^/jim\n/" /tmp/foo
# verify the content of the file has the new line prepened to it
cat /tmp/foo
Объясните и отредактируйте.
136
printf '%s\n%s\n' "to be prepended" "$(cat text.txt)" >text.txt
Это должен быть принятый ответ.
Это (1) загружает весь файл в память, и (2) вставляет весь файл в один аргумент командной строки. Хорошо для простых вещей, но остерегайтесь ограничений.
У меня было это в моем файлеgit config --get-regex $arg | sed -r 's/\t{3}/\\n/g'; и это портит, как он преобразует\t а также\n.
У этого решения есть проблемы ... оно преобразует вхождения & quot; \ n & quot; к новым строкам ... проблематично, если вы добавляете файл кода со строками, которые содержат & quot; \ n & quot ;.
В одной строке и в исходном текстовом файле! Это правильный простой ответ. Я предлагаю добавить новую строку \ n echo -e & quot; \ n $ (cat text.txt) & quot; & GT; text.txt
2

    $ echo -e "string\n" $(cat file)
Это сработало для меня ... просто небольшая модификация, чтобы сохранить мультилинии из входного файла, вы должны заключить его в кавычки, примерно так: echo -e & quot; string \ n & quot; & quot; $ (cat ~ / file.txt) & quot; & GT; ~ / File.txt;
Тогда почему бы не поднять голос @CraigWayne? Jus & APOS; & APOS говорит;
Не имеяcat Расширение параметров в двойных кавычках является довольно хорошей причиной дляdownvote, Этот код разбивает содержимое файла на слова и передает каждое из этих слов в качестве отдельного аргументаecho, Вы теряете исходные границы аргументов, вы теряете переводы строк / табуляции / и т. Д. И такие строки, как\t а также\n в исходном тексте их заменяют вкладками и символами новой строки вместо того, чтобы сохранять их прежними.
5

replace the input file:

Примечание.may have unexpected side effectsв частностиreplacing a symlink with a regular file, possibly ending up with different permissions on the file, and changing the file's creation (birth) date.

sed -i, as in Ответ принца Джона Уэсли, пытается хотя бы восстановить исходные разрешения, но применяются другие ограничения.

 { printf 'line 1\nline 2\n'; cat text.txt; } > tmp.txt && mv tmp.txt text.txt

Примечание. Использованиеgroup команда{ ...; ... } является более эффективным, чем использованиеsubshell ((...; ...)).

Еслиinput file should be edited in place (preserving its inode with all its attributes):

Используя почтенныйed POSIX utility:

Замечания:ed неизменно читает входной файлas a whole в память первым.

ed -s text.txt <<'EOF' 
1i
line 1
line 2
.
w
EOF
-s suppressed ed's status messages. Note how the commands are provided to ed as a multi-line here-document (<<'EOF' ... EOF), i.e., via stdin. 1i makes 1 (the 1st line) the current line and starts insert mode (i). The following lines are the text to insert before the current line, terminated with . on its own line. w writes the result back to the input file (for testing, replace w with ,p to only print the result, without modifying the input file).
6

printf '%s\n%s' 'text to prepend' "$(cat file.txt)" > file.txt

Обратите внимание, что это безопасно для всех видов входов, потому что нет расширений. Например, если вы хотите подготовить[email protected]#$%^&*()ugly text\n\t\n, это будет просто работать:

printf '%s\n%s' '[email protected]#$%^&*()ugly text\n\t\n' "$(cat file.txt)" > file.txt

Последняя часть, оставленная для рассмотрения, это удаление пробелов в конце файла во время подстановки команды"$(cat file.txt)", Все обходные пути для этого являются относительно сложными. Если вы хотите сохранить символы новой строки в конце file.txt, посмотрите это:https://stackoverflow.com/a/22607352/1091436

Единственная проблема с этим возникает, если содержимоеfile.txt больше, чем можно вписать в список аргументовprintf.
Любить это. Супер переносимый и не нужно создавать новый файл. Спасибо!
7

ничего встроенного, но вы можете написать свой довольно легко, например так:

#!/bin/bash
echo -n "$1" > /tmp/tmpfile.$$
cat "$2" >> /tmp/tmpfile.$$
mv /tmp/tmpfile.$$ "$2"

Нечто подобное по крайней мере ...

просто используйтеmktemp
С помощью$$ однако для производственного кода этого недостаточно (атака по символической ссылке Google); но это, безусловно, лучше, чем статическое имя файла.
+1 за использование $$ (текущий PID) как часть временного имени файла. При создании сценария для общего пользования это предотвратит возможность перезаписи временного файла другим пользователем, запустив тот же сценарий одновременно.
2

echo "Original Line" > test_file.txt

вы можете выполнить;

echo "$(echo "New Line"; cat test_file.txt)" > test_file.txt

или, если версия bash слишком старая для $ (), вы можете использовать обратные метки;

echo "`echo "New Line"; cat test_file.txt`" > test_file.txt

и получить следующее содержимое & quot; test_file.txt & quot ;;

New Line
Original Line

Нет промежуточного файла, просто bash / echo.

лучший ответ, я написал эту однострочную строку для поворота моего файла, используя этот ответ: для i в $ (& lt; file2.txt); do echo & quot; $ (echo $ i; cat file.txt) & quot; & GT; file.txt; сделанный;
26

(echo "to be prepended"; cat text.txt) > newfile.txt

Вы, вероятно, не легко обойдете промежуточный файл.

Альтернативы (может быть громоздким с экранированием оболочки):

sed -i '0,/^/s//to be prepended/' text.txt
Стратегия 1) является наиболее интуитивным из всех ответов здесь, я чувствую. И небольшое изменение:cat <(echo "to be prepended") text.txt > newfile.txt , Если подумать, я не уверен, что мое связано, поэтому я публикую отдельный ответ.
78
sed -i.old '1s;^;to be prepended;' inFile
-i writes the change in place and take a backup if any extension is given. (In this case, .old) 1s;^;to be prepended; substitutes the beginning of the first line by the given replacement string, using ; as a command delimiter.
Да, объяснение было бы здорово. Может лиinFile включить каталоги в этот путь?
@Levon Я очень хотел вставить\n, Следует ли сначала прочитать комментарии. Черт.
Обратите внимание, что \ n " работает только для GNU sed, но не для BSD (например, OSX, FreeBSD и т. д.). Чтобы быть более портативным с ними, смотрите:stackoverflow.com/questions/1421478/…
В моем случае я хочу иметь точку с запятой в конце строки, поэтому я пошел с'1s;^;my-prepended-line\;\n;'
Если бы вы могли добавить какое-то объяснение с помощью команды, это было бы полезно для тех, кто не очень знаком с работой sed. ОП может захотеть вставить в\n после предварительной подготовки; в зависимости от их потребностей. Чистое решение.
23
Process Substitution

cat <(echo "before") text.txt > newfile.txt

что, возможно, более естественно, чем принятый ответ (печатание чего-либо и передача его в команду подстановки лексикографически нелогично).

... и угоня то, что Райан сказал выше, сsponge вам не нужен временный файл:

sudo apt-get install moreutils
<<(echo "to be prepended") < text.txt | sponge text.txt

РЕДАКТИРОВАТЬ: похоже, что это не работает в Bourne Shell/bin/sh

Here String

Используя здесь-строку -<<< (опять же, вам нужен bash), вы можете сделать:

<<< "to be prepended" < text.txt | sponge text.txt
Да (хотя это не проблема конкретно с моим ответом, это неудобство оболочки). Не стесняйтесь обновлять мой ответ, если он поможет уточнить, как его использовать.
Проблема в том, что есть 1 файл, а не 2 файла. Таким образом, первая строка ответа не работает. Последняя строка может работать (но это требует губки).
Что делает губка?
@PiersyP Я согласен! Это очень помогло, спасибо, Шридхар-Сарнобат.
Этот ответ является победителем для меня. Просто и достижимо только с помощью встроенных функций. Хорошая работа!
11

ответ

Мы можем сделать это проще в использованиигубка, Теперь нам не нужно создавать временный файл и переименовывать его

echo -e "to be prepended \n another line" | cat - text.txt | sponge text.txt
это было единственное решение, работающее на меня. достаточно забавно, что мой сервер называется Спанч Боб.
0

а затем импортировать и использовать ее там, где это необходимо.

prepend_to_file() { 
    file=$1
    text=$2

    if ! [[ -f $file ]] then
        touch $file
    fi

    echo "$text" | cat - $file > $file.new

    mv -f $file.new $file
}

Тогда используйте это так:

prepend_to_file test.txt "This is first"
prepend_to_file test.txt "This is second"

Содержимое вашего файла будет:

This is second
This is first

Я собираюсь использовать этот подход для реализации средства обновления журнала изменений.

7

ен только из stdin. Тогда эта комбинация сработает.

echo "to be prepended" | cat - text.txt | tee text.txt

Если вы хотите опуститьtee вывод, затем добавьте> /dev/null.

Это далеко лучший и самый чистый ответ.
Есть ли гарантия, чтоtee не клопберtext.txt доcat получает читать это? Я думаю, что нет & # x2014; что сделало бы это решение опасным для здоровья файла.
Мне тоже нравится простота этого ответа. Он будет работать на оболочке Bourne, что не соответствует моему ответу
Мне очень нравится этот ответ. Это очень чистый и понятный способ сделать это. Использование тройника является естественным решением проблемы попытки вывода вывода во входной файл. Также нет хаков с переименованием. Лучше, чем решение, получившее наибольшее количество голосов, сейчас, поскольку оно не создает новый файл. По сути, это самое близкое к & gt; & gt; для добавления вместо добавления.
@JonathanLeffler, вероятно, нет. Я попробовал этот код для проверки:lenA=1000000; yes a | head -c $lenA > a.txt; lenB=10000; b=$(yes b | head -c $lenB); echo "$b" | cat - a.txt | tee a.txt > /dev/null, ЕслиlenA составляет 1000000 (файл 1 Мб) иlenB равно 10000 (текст 10 Кбайт), затем файл & quot; a.txt & quot; перезаписывается с помощью 20 КБ «b»; буквы. Это полностью сломано. Теперь, если вы используете 1Mb a.txt и 1Mb текст для добавления,tee заходит в цикл, генерирующий 7Gb + файл, мне пришлось остановить команду. Таким образом, очевидно, что результат непредсказуем для больших размеров. У меня нет информации, должен ли он работать на небольших размерах.
16

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

echo -e "to be prepended \n another line" | cat - text.txt

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

echo "to be prepended" | cat - text.txt > text.txt.tmp
mv text.txt.tmp text.txt
@ Левон Спасибо. Я обновил свой ответ.
это определенно напечатало бы «должен быть добавлен» а затем содержимое "text.txt". Но мне бы хотелось, чтобы текст был добавлен в файл One Two Three
а что если у меня есть многострочный текст? Как мне вставить символ новой строки в? One Two Three
Это было бы круто, но bash это не нравится: $ echo RewriteBase / | cat - web / .htaccess & gt; web / .htaccess cat: web / .htaccess: входной файл является выходным файлом
это не добавляет текст к файлуtext.txt хоть и по запросу, но отображает его на stdout. Вывод может быть направлен в другой файл, если это работает для OP
1

printf '0i\n%s\n.\nwq\n' prepend-text | ed file
0

поэтому я создал свою собственную команду:pre.

Установить с помощью go:

go get -u github.com/Flaque/pre

Добавьте текст из stdin в файл с помощью:

echo "some at the start" | pre myFile.txt | sponge myFile.txt

Команда не записывает на месте, она просто выводит на стандартный вывод, так что вам понадобитсяsponge отmoreutils в конце, чтобы сохранить файл.

Могу ли я спросить, какой максимальный размер входного файла, с которым вы это проверяли?
@CharlesDuffy Это эхо генерирует однострочный файл, интересно. Не понял, что это так.
С помощьюtee здесь небезопасно. Все части конвейера запускаются одновременно, поэтому у вас есть условие гонки с точки зрения того,pre заканчивает чтение старого содержимого файла доtee усекает файл назначения для записи.
@CharlesDuffy Это по общему признанию начинает занимать необоснованное время в файле 977K, который я сгенерировал:yes "some text" | head -n 100000 > large-file а затем побежал:cat large-file | pre large-file
Пытатьсяecho "One line" | pre large-file | tee large-fileи проверьте размер выходного файла, который генерируется.
3

sed:

sed -i.old '1 {i to be prepended
}' inFile

Если добавляемая строка многострочная:

sed -i.old '1 {i\ 
to be prepended\
multiline
}' inFile
Почему бы и нетsed -i '1ito be prepended' inFile - или это разрешено только для GNU sed?
@userunknown: в стандартеsed,i за командой следует обратная косая черта и новая строка, и каждая строка ввода, кроме последней, заканчивается обратной косой чертой. GNUsed позволяет использовать сокращения в соответствии с тем, о чем вы спрашиваете, но это только GNUsed это делает так.

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