ファイルにテキストを付加するUnixコマンド


124

テキストファイルに文字列データを付加するUnixコマンドはありますか?

何かのようなもの:

prepend "to be prepended" text.txt

単一のコマンドを探していますか、それとも小さなスクリプト/エイリアスコマンドで問題ありませんか?
Levon、2012年

2
:あなたはすべての答えを組み合わせた場合、これはおそらく最もコンパクトな方法である<<(echo "to be prepended") < text.txt | sponge text.txt
シュリダールSarnobat

回答:


110
sed -i.old '1s;^;to be prepended;' inFile
  • -i変更を適切に書き込み、拡張子が指定されている場合はバックアップを取ります。(この場合、.old
  • 1s;^;to be prepended;;コマンドの区切り文字として使用して、最初の行の先頭を指定された置換文字列で置き換えます。

19
コマンドを使用して説明を追加できれば、sedの動作にあまり詳しくない他の人に役立つでしょう。OPは\n先頭に追加したい場合があります。彼らのニーズに応じて。きちんとしたソリューション。
Levon

ええ、説明は素晴らしいでしょう。inFileパスにディレクトリを含めることはできますか?
ザクダンス2013年

3
@Levon私は完全にを挿入したかった\n。最初にコメントを読むべきだった。くそー。
chishaku

私の場合、先頭行の最後にセミコロンを付けたいので、一緒に行きました'1s;^;my-prepended-line\;\n;'
SamGamgee

5
'\ n'はGNU sedでのみ機能し、BSD(OSX、FreeBSDなど)では機能しないことに注意してください。それらをより移植可能にするには、以下を参照してくださいstackoverflow.com/questions/1421478/...
JWD

162
printf '%s\n%s\n' "to be prepended" "$(cat text.txt)" >text.txt

2
1行で、元のテキストファイルに!これが正解です。追加の新しい行を提案します\ n echo -e "先頭に追加する\ n $(cat text.txt)"> text.txt
VincentPerrin.com

32
このソリューションには問題があります。「\ n」の出現を実際の新しい行に変換します...「\ n」を含む文字列を含むコードファイルの前に付加する場合は問題があります。
Paul Go

1
私はこれを自分のファイルに入れgit config --get-regex $arg | sed -r 's/\t{3}/\\n/g';ましたが、\tとを変換するときにこれがめちゃくちゃになり\nます。
hIpPy 2017

8
これは、(1)ファイル全体をメモリにロードし、(2)ファイル全体を単一のコマンドライン引数に貼り付けます。単純なものには問題ありませんが、制限に注意してください。
jwd 2017年

2
最後に試したところ、本当に大きなファイルが壊れると思います。猫は、上書きされる前にtext.txtの内容全体を読み取ることができません。エコーの-eオプションが問題である場合は、bashまたはdoで改行を引用できますecho "to be prepended"$'\n'"$(cat text.txt)"
jbo5112

41

プロセス置換

誰もこれに言及しなかったのには驚きです。

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

これは、受け入れられた回答よりも間違いなく自然です(何かを出力して置換コマンドにパイプすることは、辞書式順序的に直観に反しています)。

...そして、ライアンが上で言ったことをハイジャックしspongeます、あなたは一時ファイルを必要としません:

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

編集:これはボーンシェルでは機能しないようです /bin/sh


Here String(zshのみ)

here-string-を使用すると<<<、次のことができます。

<<< "to be prepended" < text.txt | sponge text.txt

3
この答えは私にとって勝者です。ビルトインのみでシンプルかつ達成可能。よくできました!
PiersyP

1
@PiersyP同意する!これは非常に役に立ちました。Sridhar-Sarnobatに感謝します。

問題は、2つのファイルではなく1つのファイルがあることです。したがって、答えの最初の行は実際には機能しません。最後の行が機能する可能性があります(ただし、スポンジが必要です)。
VasiliNovikov

1
スポンジは何をしますか?
Hemanta

1
あなた<<(echo "to be prepended") < text.txt<<< "to be prepended" < text.txtの構成は、bashで動作しません。zshが必要です。
アンデルスカセオルグ

31

これは1つの可能性です。

(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 。考えてみてください、私が関連しているのかどうかわかりませんので、別の答えを投稿します。
Sridhar Sarnobat

1
最初の方法ではファイルのアクセス許可が保持されません
Xlsx

権限を保持する唯一の方法は、スポンジを使用することです
Sridhar Sarnobat

19

これは、出力を形成するために機能します。-は、エコーからのパイプを介して提供される標準入力を意味します。

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

2
これはtext.txt、要求に応じてテキストをファイルの先頭に追加しませんが、標準出力に表示します。OPで機能する場合は、出力を別のファイルにまとめることができます
Levon

1
これは間違いなく「先頭に追加されます」と「text.txt」の内容を印刷します。しかし、テキストをファイルの先頭に追加したいと思います
One Two Three

1
複数行のテキストがある場合はどうなりますか?そこに改行文字を入れるにはどうすればよいですか?
One Two Three

これはかっこいいですが、bashは好きではありません:$ echo RewriteBase / | cat-web / .htaccess> web / .htaccess cat:web / .htaccess:input file is output file
geek-merlin

14

アダムの答えを好む

スポンジを使いやすくすることができます。これで、一時ファイルを作成して名前を変更する必要がなくなりました。

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

これが私にとって有効な唯一の解決策でした。私のサーバーの名前がスポンジボブであるのは十分面白いです。
オメルアン

9

交換しても差し支えない場合入力ファイル:

注意:

  • これを行うと、予期しない副作用が発生する可能性があります。特に、シンボリックリンクを通常のファイルに置き換えたり、ファイルに対するさまざまな権限を取得したり、ファイルの作成(生)日付を変更したりする可能性があります。

  • sed -iPrince John Wesleyの回答のように、少なくとも元の権限を復元しようとしますが、他の制限も適用されます。

一時ファイルを使用する簡単な代替方法を次に示しますshimeのソリューションのように、入力ファイル全体をメモリに読み込むのを避けます)。

{ printf 'to be prepended'; cat text.txt; } > tmp.txt && mv tmp.txt text.txt

使用グループコマンドは({ ...; ...; })を使用して、よりわずかに効率的であるサブシェルを(...; ...)と)0xC0000022Lの溶液

利点は次のとおりです。

  • 新しいテキストを最初の行に直接追加するか、新しい行として挿入するか(単に引数に追加\nするprintfか)を制御するのは簡単です。

  • sedソリューションとは異なり、入力ファイルが空(0バイト)の場合に機能します。


sed溶液は意図は、1つまたは複数の前に付加する場合を簡略化することができる全体の行を(入力ファイルが空であると仮定して)既存のコンテンツに:

sedi関数は行全体を挿入します。

GNU sed

# Prepends 'to be prepended' *followed by a newline*, i.e. inserts a new line.
# To prepend multiple lines, use '\n' as part of the text.
# -i.old creates a backup of the input file with extension '.old'
sed -i.old '1 i\to be prepended' inFile

macOS / BSDでも動作するポータブルバリアントsed

# Prepends 'to be prepended' *followed by a newline*
# To prepend multiple lines, escape the ends of intermediate
# lines with '\'
sed -i.old -e '1 i\
to be prepended' inFile

の後のリテラルの改行\は必須です。


入力ファイルをそので編集する必要がある場合(そのiノードをすべての属性とともに保持します):

由緒あるedPOSIXユーティリティの使用

注意:

  • ed常に最初に入力ファイル全体を常にメモリに読み込みます。

する最初の行に直接的にプリペンド(と同様にsed、入力ファイルが完全に(空の場合、これは動作しません0)バイト):

ed -s text.txt <<EOF
1 s/^/to be prepended/
w
EOF
  • -sedのステータスメッセージを抑制しました。
  • コマンドがed複数行のhere-document<<EOF\n...\nEOF)として、つまりstdinを介して提供されることに注意してください。デフォルトで、そのようなドキュメントで文字列展開実行されます(シェル変数は補間されます)。それを抑制するために開始区切り文字を引用します(たとえば、<<'EOF'
  • 1 1行目を現在の行にします
  • 関数sは、次のように、現在の行で正規表現ベースの文字列置換を実行しsedます。置換テキストにリテラルの改行を含めることができますが、それらは\エスケープする必要があります。
  • w(テストのために、交換してください入力ファイルへの結果の背中を書き込んw,pのみに印刷し、入力ファイルを変更せずに、結果を)。

1つ以上の行全体先頭に追加するには

と同様にsed、このi関数は挿入するテキストに必ず末尾の改行を追加します。

ed -s text.txt <<EOF
0 i
line 1
line 2
.
w
EOF
  • 0 iMAKES 0(ファイルの先頭)モード、インサート現在の行と開始(i); それ以外の場合は行番号が1ベースになることに注意してください。
  • 次の行は、現在の行のに挿入するテキストで、1行で終了し.ます。

7

おそらく何も組み込まれていませんが、次のようにして自分で簡単に作成できます。

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

少なくともそのような何か...


6
一時ファイル名の一部として$$(現在のPID)を使用する場合は+1。一般的に使用するスクリプトを作成する場合、これにより、別のユーザーが同じスクリプトを同時に実行して一時ファイルを上書きするのを防ぐことができます。
Eブラウン

3
$$ただし、本番用コードでは使用は不十分です(グーグルsymlink攻撃)。しかし、それは確かに静的ファイル名よりも優れています。
Tripleee

1
使用するだけmktemp
-mewa

7

状況によっては、先頭に追加されたテキストはstdinからしか利用できない場合があります。次に、この組み合わせが機能します。

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

tee出力を省略したい場合は、を追加します> /dev/null


私はこの答えが本当に好きです。これは、非常にクリーンで明確な方法です。teeの使用は、出力を入力ファイルにcatしようとする問題の自然な解決策です。また、名前を変更するハックもありません。新しいファイルを作成しないため、現時点で最も投票数の多いソリューションより優れています。これは基本的に、追加する代わりに前に追加するために>>に到達する最も近いものです。
DC2 2017年

これは最善かつ最も明確な答えです。
nerdoc 2018

6
それを読む前にtee破壊されないという保証はありますか?私はそうは思いません—これはこの解決策をファイルの健康にとって危険にするでしょう。text.txtcat
ジョナサンレフラー

3
@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。場合はlenA1000000(1MBのファイル)で、lenB10000(10KBテキストプリペンド)で、そのファイル「A.TXT」は「B」の文字の20KBで上書きされます。これは完全に壊れています。ここで、1Mb a.txtと1Mbテキストを使用して先頭に追加し、tee7Gb +ファイルを生成するループに入る場合、コマンドを停止する必要がありました。したがって、サイズが大きい場合の結果は予測できないことは明らかです。小さいサイズでも動作するかどうかはわかりません。
VasiliNovikov

3
概念的に言えば、このコマンドは、入力ファイルがシステムのパイプラインバッファーサイズ(最近の通常は64 KB)より大きい場合、データを損失します
mklement0

7

解決:

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

展開がないため、これはすべての種類の入力で安全です。たとえば、を先頭に追加する場合は、次のように機能します!@#$%^&*()ugly text\n\t\n

printf '%s\n%s' '!@#$%^&*()ugly text\n\t\n' "$(cat file.txt)" > file.txt

考慮すべき最後の部分は、コマンド置換中のファイルの終わりでの空白の削除"$(cat file.txt)"です。これに対するすべての回避策は比較的複雑です。file.txtの最後の改行を保持したい場合は、次を参照してください:https : //stackoverflow.com/a/22607352/1091436


大好きです。非常にポータブルで、新しいファイルを生成する必要はありません。ありがとう!
pyb

1
これに関する唯一の問題は、の内容がfile.txtへの引数リストに適合できるよりも大きい場合に発生しprintfます。
ジョナサンレフラー

6

別の使用方法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コマンドの後にバックスラッシュと改行が続き、最後の行を除く各入力行もバックスラッシュで終わります。GNU sedはあなたが尋ねる行に沿った省略表現を許可しますが、そうするのはGNUだけsedです。
ジョナサンレフラー

3

Bash(Ubuntu)でテストしたとおり、テストファイルから開始した場合

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

そして、「test_file.txt」の以下の内容を受け取ります。

New Line
Original Line

中間ファイルはなく、bash / echoのみです。


2
最良の答えは、この答えを使用してファイルをローテーションするためのこの1行のコードです。fori in $(<file2.txt); echo "$(echo $ i; cat file.txt)"> file.txt; 完了。
Aurangzeb

2

別のかなり簡単な解決策は次のとおりです。

    $ echo -e "string\n" $(cat file)

これは私にとってはうまくいきました...入力ファイルの複数行を維持するために、次のように引用符で囲む必要があります:echo -e "string \ n" "$(cat〜/ file.txt) ">〜/ file.txt;
クレイグウェイン

2
cat二重引用符でパラメーターを展開しないことは、反対票を投じる十分な理由です。このコードは、ファイルの内容を単語に分割し、それらの各単語を個別の引数としてに渡しますecho。あなたは、元の引数の境界を失い、あなたは改行/タブの/ etc。失う、とのような文字列\t\n、元のテキストでは、タブ、改行の代わりに、彼らがいたとして保持された状態で置き換えられます。
Charles Duffy


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

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

このアプローチを使用して、変更ログのアップデーターを実装しようとしています。

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