Як додати текст до початку файлу в Bash?


285

Привіт, я хочу додати текст до файлу. Наприклад, я хочу додати завдання до початку файлу todo.txt. Мені відомо, echo 'task goes here' >> todo.txtале це додає рядок до кінця файлу (не те, що я хочу).


2
Там, якщо немає ефективного способу зробити це для великих файлів: unix.stackexchange.com/questions/87772/…
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

@ ви могли поглянути на цей метод superuser.com/a/1352628/11116
Еван Керролл

Відповіді:


374
echo 'task goes here' | cat - todo.txt > temp && mv temp todo.txt

або

sed -i '1s/^/task goes here\n/' todo.txt

або

sed -i '1itask goes here' todo.txt

4
перший чудово працює! Ви не проти пояснити логіку? Я не особливо впевнений, як інтерпретувати синтаксис.
користувач479534

44
@ user8347: Труба ( |) повідомлення ( echo '...'), catяке використовує -(стандартний вхід) як перший файл, так і todo.txtяк другий. catз'єднує декілька файлів. Надішліть вихід ( >) до файлу з назвою temp. Якщо немає помилок ( &&), catперейменуйте ( mv) tempфайл назад у вихідний файл ( todo.txt).
Денніс Вільямсон

1
@itaifrenkel: Я повинен був би побачити, що ти зробив, але якщо catотримає буквальний зворотний косий n, він не перетворить його на новий рядок. Щось, мабуть, зробив це. Замість цього catспробуйте ввімкнути, hexdump -Cщоб побачити, чи ви насправді надсилаєте зворотну косу риску та n чи це новий рядок. Ви також можете спробувати cat -eпоказати закінчення рядків.
Денніс Вільямсон

1
Використання 2 і 3 (3 мені здається більш простим) дозволяє вам додавати текст одночасно до багатьох файлів.
Фелікс

4
@Kira: Засіб 1виконує наступну команду лише в рядку першого файлу і iкоманда вставляється. Подивіться на сторінку довідника в розділі «Адреси» та в розділі «Команди нульової або однієї адреси».
Денніс Вільямсон,

73

Більш простий варіант на мою думку:

echo -e "task goes here\n$(cat todo.txt)" > todo.txt

Це працює, тому що команда всередині $(...)виконується раніше, ніж todo.txtперезаписана> todo.txt

Хоча інші відповіді спрацьовують добре, мені це набагато легше запам’ятати, оскільки я використовую ехо та кішку щодня.

EDIT: Це рішення є дуже поганою ідеєю, якщо є зворотні риски todo.txt, тому що завдяки -eпрапорці відлуння їх інтерпретуватиме. Ще один, набагато простіший спосіб ввести нові рядки в рядок передмови ...

echo "task goes here
$(cat todo.txt)" > todo.txt

... просто використовувати нові рядки. Звичайно, це вже не однолінійний лайнер, але реально він раніше не був одноразовим. Якщо ви робите це всередині сценарію, і переймаєтесь відступом (наприклад, виконайте це всередині функції), є кілька способів вирішити цю проблему, включаючи, але не обмежуючись цим:

(echo 'task goes here' && cat todo.txt) > todo.txt
echo 'task goes here'$'\n'"$(cat todo.txt)" > todo.txt

Крім того, якщо вам важливо, чи буде доданий новий рядок до кінця todo.txt, не використовуйте їх. Ну, крім другого до останнього. Це не псується з кінцем.


1
Я взагалі не отримую $ (...).
SCL

2
Це може працювати краще (або зовсім) з подвійними цитатами замість одиничних…
phaphink

5
Чи не -eперетворять також послідовності втечі в todo.txt?
mk12

2
Обхідні показники врожайності -> cat: <ім'я файлу призначення>: вхідний файл - вихідний файл ...
ingyhere

printf був би набагато послідовнішим на всіх платформах і, як правило, працював би більш плавно, ніж відлуння -е
Пітер Берг

28

moreutilsЄ хороший інструмент під назвою sponge:

echo "task goes here" | cat - todo.txt | sponge todo.txt

Він "просочить" STDIN і запише у файл, а це означає, що вам не доведеться турбуватися про тимчасові файли та переміщення їх.

Ви можете отримати moreutilsз багатьма дистрибутивами Linux, через apt-get install moreutilsабо на OS X, використовуючи Homebrew , за допомогою brew install moreutils.


Я б пішов на (echo 'ble'; cat todo.txt):-)
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

11

Ви можете використовувати Vim в режимі Ex:

ex -s -c '1i|task goes here' -c x todo.txt
  1. 1 виберіть перший рядок

  2. i вставити

  3. x зберегти і закрити


5

Ви можете створити новий тимчасовий файл.

echo "new task" > new_todo.txt
cat todo.txt >> new_todo.txt
rm todo.txt
mv new_todo.txt todo.txt

Ви також можете використовувати sedабо awk. Але в основному відбувається те саме.


1
Скажімо, у вас немає місця на диску, щоб new_todo.txtзаписати його частково. Схоже, ваше рішення втрачає оригінальний файл.
NPE

У кого не вистачає місця на диску? ;-) Це просто простий приклад.
Кіт

2
@Keith Хтось, хто працює на машині, що не сподівався потребувати особливо великого віртуального накопичувача. Або хтось переміщує великий файл. У будь-якому випадку реальним аргументом проти цього є дозволи довідників; якщо у вас немає дозволу на створення нових файлів у даному каталозі, єдиною командою, яка буде успішно виконана у вашому скрипті, є rmвихідний файл.
Парфянський розстріл

3

Якщо текстовий файл є досить малим, щоб вмістити його в пам'яті, вам не доведеться створювати тимчасовий файл для його заміни. Ви можете завантажити все це в пам'ять і записати назад у файл.

echo "$(echo 'task goes here' | cat - todo.txt)" > todo.txt

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


Просто, щоб задати очевидне питання: Де обмеження символів змінних оболонок?
nixda

Наскільки мені відомо, він обмежений лише кількістю наявної пам’яті. Я заповнив змінні значно більше 100 МБ в пам'ять. text=$(cat file). Будьте обережні, але використовуйте лише текст, тому що змінні оболонки не є бінарними чистими mywiki.wooledge.org/BashFAQ/058
Rucent88

2

Ви не можете вставити вміст на початку файлу. Єдине, що ви можете зробити, це або замінити наявний вміст, або додати байти після поточного кінця файлу.

Будь-яке рішення вашого питання вимагає створити тимчасовий файл (або буфер) (на пам'яті або на диску), який згодом перезапише оригінальний файл.

Остерігайтеся не втрачати дані, зберігаючи оригінальний файл під час створення нового, якщо файлова система під час процесу буде повною. наприклад:

cat <(echo task go there) todo.txt > todo.txt.new && mv todo.txt.new todo.txt

Лайдаки можуть прояснити мотивацію. Жодна з решти відповідей, включаючи прийняту, нічого не суперечить моїй відповіді.
jlliagre

Це важко проаналізувати, оскільки <...> виглядають як дужки, і я вважаю, що це не так. Пробіл між <і (може допомогти?
dumbledad

Це не працює для мене. echo HOME=\"/g/Users/timregan/\" | cat - 'F:\Program Files\Git\etc\profile'працює, але cat <echo HOME=\"/g/Users/timregan/\" 'F:\Program Files\Git\etc\profile'видає помилку "ехо: Немає такого файлу чи каталогу"
dumbledad

@dumbledad Ви переосмислюєте мою відповідь. Немає для вас розбору в цьому. Пробіл між і <та (перерве синтаксис. Спробуйтеcat <(echo HOME=\"/g/Users/timregan/\") 'F:\Program Files\Git\etc\profile'
jlliagre


0

GitBash + Windows10 + Multline :

Ось версія, яка дозволяє використовувати багаторядкові рядки .

##############################################
## This section for demo purpose only,      ##
## So you can save entire file as           ##
## whatever.sh and run it.                  ##
##                                          ##
##############################################
> MY_TARGET_FILE.txt ##Make Or Clear File
echo "[STARTER_CONTENT]" >> MY_TARGET_FILE.txt
##############################################

## Below is main code:

##################################################
TARGET_FILE_VARIABLE="MY_TARGET_FILE.txt"
ADD_TO_HEAD_VARIABLE=$(cat << "HEREDOC_HEAD_TEXT"
//|  +-------------------------------------+   |//
//|  |                                     |   |//
//|  |     MESSAGE_FOR_HEAD_OF_FILE        |   |//
//|  |                                     |   |//
//|  +-------------------------------------+   |//
HEREDOC_HEAD_TEXT
)
##################################################
TAR=$TARGET_FILE_VARIABLE                       ##
TEX=$ADD_TO_HEAD_VARIABLE                       ##
echo "$TEX" | cat - $TAR > TEMP && mv TEMP $TAR ##
##################################################

## Expected contents of MY_TARGET_FILE.txt :
## //|  +-------------------------------------+   |//
## //|  |                                     |   |//
## //|  |     MESSAGE_FOR_HEAD_OF_FILE        |   |//
## //|  |                                     |   |//
## //|  +-------------------------------------+   |//
## [STARTER_CONTENT]
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.