Bashでファイルの先頭にテキストを追加するにはどうすればよいですか?


285

こんにちは、ファイルにテキストを追加します。たとえば、todo.txtファイルの先頭にタスクを追加します。私は知っていますがecho 'task goes here' >> todo.txt、それはファイルの最後に行を追加します(私が望むものではありません)。


2
そこに大きなファイルのためにそれを行うには効率的な方法の場合:unix.stackexchange.com/questions/87772/...
チロ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
最初のものは素晴らしい作品です!論理を説明してもらえますか?構文の解釈方法が特にわかりません。
user479534

44
@ user8347:最初のファイルと2番目のファイルとして(標準入力)を使用|するメッセージ(echo '...')をパイプ()します。複数のファイルを連結します。出力()をという名前のファイルに送信します。エラーがない場合()から、ファイル名を変更()して元のファイルに戻します()。cat-todo.txtcat>temp&&catmvtemptodo.txt
デニスウィリアムソン

1
@itaifrenkel:あなたが何をしたかを見なければcatなりませんが、文字通りバックスラッシュnを受け取った場合、改行に変換しません。他の何かがそれをしたに違いない。の代わりにcathexdump -C実際にバックスラッシュとnを送信しているか、それが改行かを確認するためにパイピングしてみてください。cat -e行末を表示することもできます。
デニスウィリアムソン14年

1
2と3(3は3の方が簡単そうです)を使用すると、一度に多くのファイルにテキストを追加できます。
フェリックス14年

4
@Kira:1ファイルの1行目でのみ次のコマンドを実行し、iコマンドは挿入されます。「アドレス」セクションの「manページ」と「ゼロまたは1アドレスのコマンド」セクションをご覧ください。
デニスウィリアムソン

73

私の意見では、より簡単なオプションは次のとおりです。

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

これは、内部のコマンドが上書き$(...)される前に実行されるため機能しtodo.txtます> todo.txt

他の答えはうまくいきますが、私は毎日echoとcatを使用しているため、これはずっと覚えやすいと思います。

編集:このソリューションは、バックスラッシュがある場合todo.txt-eフラグエコーのおかげでバックスラッシュが解釈されるため、非常に悪い考えです。序文文字列に改行を入れるもう1つのはるかに簡単な方法は...

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

...単に改行を使用します。確かに、これはもう1ライナーではありませんが、現実的には以前は1ライナーではありませんでした。スクリプト内でこれを行っており、インデントが心配な場合(たとえば、関数内でこれを実行している場合)、これをうまくフィットさせるためのいくつかの回避策があります。

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

また、の末尾に改行が追加されるかどうかを気にする場合はtodo.txt、これらを使用しないでください。まあ、最後から2番目を除いて。それは終わりを台無しにしません。


1
私は$(...)を実行しません。
SCL

2
それは、シングルクォートの代わりにダブルクォートでより良く(またはまったく)動作するかもしれません…
phinaphink

5
-etodo.txt内のエスケープシーケンスも変換しませんか?
mk12

2
回避策
yield-

printfはプラットフォーム間ではるかに一貫性があり、一般的にecho -e
Peter Berg

28

moreutils呼ばれる便利なツールを持っていますsponge

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

STDINを「吸収」してからファイルに書き込みます。つまり、一時ファイルを心配したり、ファイルを移動したりする必要はありません。

あなたは得ることができmoreutilsて、多くのLinuxディストリビューションをapt-get install moreutils使用して、またはOS X上で自作して、brew install moreutils


私はのために行くだろう(echo 'ble'; cat todo.txt):-)
チロSantilli新疆改造中心法轮功六四事件

11

ExモードでVimを使用できます。

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特に大きな仮想ドライブが必要になるとは思わなかったVMで作業している人。または誰かが大きなファイルを移動します。いずれにせよ、これに対する本当の議論はディレクトリの許可です。指定したディレクトリに新しいファイルを作成する権限がない場合、スクリプトで正常に実行されるコマンドrmは元のファイルのみです。
パルティアショット14

3

テキストファイルがメモリに収まるほど小さい場合は、一時ファイルを作成して置き換える必要はありません。すべてをメモリにロードし、ファイルに書き戻すことができます。

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

ファイル全体を上書きせずにファイルの先頭に行を追加することは不可能です。


明らかな質問をするだけです:シェル変数の文字制限はどこにありますか?
-nixda

私の知る限り、利用可能なメモリの量によってのみ制限されます。100MBをはるかに超える変数をメモリに埋めました。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

Downvotersは彼らの動機を説明することを歓迎します。受け入れられたものを含め、残りの答えはどれも私の返信で矛盾しません。
jlliagre

<...>は括弧のように見えるので、これを解析するのは困難ですが、そうではないと思います。<と(の間にスペースがあると
便利

これは私のために働いていません。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 + マルチライン

これは、複数行の文字列を使用できるバージョンです。

##############################################
## 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]
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.