135

これはおそらく複雑なソリューションです。

">>" のような単純な演算子を探していますが、先頭に追加します。

私はそれが存在しないことを恐れています。私は次のようなことをしなければならないでしょう

mv myfile tmp
 cat myheader tmp > myfile

もっと賢いものはありますか?

4

34 に答える 34

105

これはまだ一時ファイルを使用していますが、少なくとも 1 行です。

echo "text" | cat - yourfile > /tmp/out && mv /tmp/out yourfile

クレジット: BASH: テキスト/行をファイルに追加する

于 2008-09-10T15:21:26.127 に答える
32
echo '0a
your text here
.
w' | ed some_file

ed は標準エディターです。http://www.gnu.org/fun/jokes/ed.msg.html

于 2010-07-17T16:24:17.397 に答える
30

以下のハックは、すぐに使える簡単な回答であり、機能し、多くの賛成票を獲得しました. その後、質問の人気が高まり、時間が経つにつれて、憤慨した人々が、それはある程度機能したが、奇妙なことが起こる可能性がある、またはまったく機能しなかったと報告し始めたため、しばらくの間、猛烈に反対票が投じられました. とても楽しい。

このソリューションは、システム上のファイル記述子の正確な実装を利用します。実装は nix 間で大幅に異なるため、成功は完全にシステムに依存し、決定的に移植性がなく、漠然と重要であっても信頼すべきではありません。

さて、それで答えは次のとおりでした。


ファイル ( )の別のファイル記述子を作成し、そのファイル ( exec 3<> yourfile) に>&3書き込むことで、同じファイルの読み取り/書き込みのジレンマを克服できるようです。awk を使用して 600K ファイルで動作します。ただし、「cat」を使用して同じトリックを試みると失敗します。

前置を変数として awk( -v TEXT="$text") に渡すと、「sed」でこのトリックを実行できないリテラルの引用符の問題が解決されます。

#!/bin/bash
text="Hello world
What's up?"

exec 3<> yourfile && awk -v TEXT="$text" 'BEGIN {print TEXT}{print}' yourfile >&3
于 2009-03-07T12:43:49.330 に答える
20

John Mee: あなたのメソッドは動作することが保証されておらず、4096 バイトを超えるものを先頭に追加するとおそらく失敗します (少なくとも gnu awk ではそうなりますが、他の実装にも同様の制約があると思います)。その場合、失敗するだけでなく、独自の出力を読み取る無限ループに入り、使用可能なすべてのスペースがいっぱいになるまでファイルが大きくなります。

自分で試してみてください:

exec 3<>myfile && awk 'BEGIN{for(i=1;i<=1100;i++)print i}{print}' myfile >&3

(警告: しばらくしてから終了するか、ファイルシステムがいっぱいになります)

さらに、そのようにファイルを編集することは非常に危険であり、非常に悪いアドバイスです。ファイルの編集中に何かが発生した場合 (クラッシュ、ディスクがいっぱいになるなど)、ファイルが一貫性のない状態のままになることがほぼ保証されます。

于 2010-05-02T16:03:15.637 に答える
19

一時ファイルなしでは不可能ですが、ここにワンライナーがあります

{ echo foo; cat oldfile; } > newfile && mv newfile oldfile

ed や perl などの他のツールを使用して、一時ファイルなしで実行できます。

于 2008-09-10T15:22:22.740 に答える
17

制御するコンピューターでこれが必要な場合は、パッケージ「moreutils」をインストールし、「sponge」を使用してください。次に、次のことができます。

cat header myfile | sponge myfile
于 2013-03-30T17:10:17.650 に答える
16

少なくともスクリプトがルート権限で実行される場合は、mktempなどのユーティリティを使用して一時ファイルを安全に生成することをお勧めします。たとえば、次のようにすることができます (これも bash で)。

(tmpfile=`mktemp` && { echo "prepended text" | cat - yourfile > $tmpfile && mv $tmpfile yourfile; } )
于 2008-09-12T16:51:54.147 に答える
10

編集するファイルがmy.txtであると仮定します

$cat my.txt    
this is the regular file

そして、あなたが追加したいファイルはヘッダーです

$ cat header
this is the header

ヘッダーファイルには必ず最後の空白行を入れてください。
今、あなたはそれを前に付けることができます

$cat header <(cat my.txt) > my.txt

あなたは

$ cat my.txt
this is the header
this is the regular file

私の知る限り、これは「bash」でのみ機能します。

于 2009-07-16T14:09:13.800 に答える
9

シェルスクリプトで困難になることをしようとし始めたら、「適切な」スクリプト言語 (Python/Perl/Ruby/etc) でスクリプトを書き直すことを強くお勧めします。

ファイルの前に行を追加することに関しては、パイピングを介してこれを行うことはできませんcat blah.txt | grep something > blah.txtspongeインストールできる小さなユーティリティ コマンドがあります (インストールするcat blah.txt | grep something | sponge blah.txtと、ファイルの内容がバッファリングされ、ファイルに書き込まれます)。これは一時ファイルに似ていますが、明示的に行う必要はありません。しかし、それはたとえば Perl よりも「悪い」要件だと思います。

awkなどを介して行う方法があるかもしれませんが、シェルスクリプトを使用する必要がある場合は、一時ファイルが最も簡単な(/のみ?)方法だと思います..

于 2008-09-14T23:08:41.447 に答える
8

ダニエル・ベルコフが示唆するように、ティーを使用してください。
私にとって、それはシンプルでスマートなソリューションです。

{ echo foo; cat bar; } | tee bar > /dev/null
于 2012-02-28T16:01:31.063 に答える
7

編集:これは壊れています。catとteeを含むファイルの前に追加するときの奇妙な動作を参照してください

上書きの問題の回避策は次のteeとおりです。

cat header main | tee main > /dev/null
于 2010-10-26T19:49:49.883 に答える
5
sed -i -e "1s/^/new first line\n/" old_file.txt
于 2010-09-30T22:34:49.723 に答える
3

$( command )を使用すると、コマンドの出力を変数に書き込むことができます。そのため、一時ファイルを使用せずに、3 つのコマンドを 1 行で実行しました。

originalContent=$(cat targetfile) && echo "text to prepend" > targetfile && echo "$originalContent" >> targetfile
于 2014-01-05T07:14:22.107 に答える
3

主にファン/シェルゴルフ用ですが、

ex -c '0r myheader|x' myfile

トリックを行い、パイプラインやリダイレクトはありません。もちろん、vi/ex は実際には非対話的な使用向けではないため、vi が短時間フラッシュします。

于 2013-07-08T17:21:32.583 に答える
3

私が使っているもの。これにより、順序、追加の文字などを好きなように指定できます。

echo -e "TEXTFIRSt\n$(< header)\n$(< my.txt)" > my.txt

PS: ファイルにバックスラッシュ付きのテキストが含まれている場合のみ機能しません。エスケープ文字として解釈されるためです。

于 2011-05-24T09:19:18.550 に答える
2

警告:これには、OPのニーズを満たすためにもう少し作業が必要です。

@shixilunによるsedアプローチを、彼の不安にもかかわらず機能させる方法があるはずです。ファイルをsed置換文字列に読み込むときに空白をエスケープするには、bashコマンドが必要です(たとえば、改行文字を'\ n'に置き換えます。シェルコマンドは印刷できない文字viscat処理できますが、空白は処理できないため、OPは解決されません。問題:

sed -i -e "1s/^/$(cat file_with_header.txt)/" file_to_be_prepended.txt

置換スクリプトの生の改行が原因で失敗します。これは、行継続文字()を前に付け、シェルとsedを幸せに保つために、おそらく&を続ける必要があります。このSO回答のように

sed非グローバル検索置換コマンドのサイズ制限は40Kであるため(パターンの後に/ gが続くことはありません)、匿名で警告されたawkの恐ろしいバッファオーバーランの問題を回避できる可能性があります。

于 2011-03-06T08:11:55.997 に答える
2

これが私が発見したものです:

echo -e "header \n$(cat file)" >file
于 2011-11-21T07:24:37.550 に答える
2

単純に ed コマンドを使用しないのはなぜですか (fluffle here で既に提案されているように)。

ed はファイル全体をメモリに読み込み、その場でファイル編集を自動的に実行します!

したがって、ファイルがそれほど大きくない場合...

# cf. "Editing files with the ed text editor from scripts.",
# http://wiki.bash-hackers.org/doku.php?id=howto:edit-ed

prepend() {
   printf '%s\n' H 1i "${1}" . wq | ed -s "${2}"
}

echo 'Hello, world!' > myfile
prepend 'line to prepend' myfile

さらに別の回避策は、 Redirect output from sed 's/c/d/' myFile to myFileで Jürgen Hötzel によって提案されているように、開いているファイル ハンドルを使用することです。

echo cat > manipulate.txt
exec 3<manipulate.txt
# Prevent open file from being truncated:
rm manipulate.txt
sed 's/cat/dog/' <&3 > manipulate.txt

もちろん、これらすべてを 1 行にまとめることもできます。

于 2011-04-08T09:23:18.440 に答える
2

固定テキストを先頭に追加するための「一時ファイルなし」のcb0のソリューションのバリアント:

echo "text to prepend" | cat - file_to_be_modified | ( cat > file_to_be_modified ) 

繰り返しますが、これはサブシェルの実行 ((..)) に依存しており、cat が入力と出力に同じファイルを使用することを拒否することを回避しています。

注:このソリューションが気に入りました。ただし、私の Mac では元のファイルが失われます (そうあるべきではないと思っていましたが、実際に失われます)。これは、ソリューションを次のように記述することで修正できます。猫 - file_to_be_modified | 猫 > tmp_file; mv tmp_file file_to_be_modified

于 2010-03-02T11:57:43.213 に答える
2
sed -i -e '1rmyheader' -e '1{h;d}' -e '2{x;G}' myfile
于 2012-05-06T15:30:20.870 に答える
1

実際、BASH でスクリプトを作成している場合は、次のように発行できます。

cat - yourfile /tmp/out && mv /tmp/out yourfile

それは実際には、あなた自身が自分の質問に投稿した複雑な例にあります。

于 2008-09-11T05:00:50.917 に答える
1

大きなファイル (私の場合は数百キロバイト) があり、Python にアクセスできる場合、これはcatパイプ ソリューションよりもはるかに高速です。

python -c 'f = "filename"; t = open(f).read(); open(f, "w").write("text to prepend " + t)'

于 2014-10-12T21:42:25.920 に答える
0

変数、ftw?

NEWFILE=$(echo deb http://mirror.csesoc.unsw.edu.au/ubuntu/ $(lsb_release -cs) main universe restricted multiverse && cat /etc/apt/sources.list)
echo "$NEWFILE" | sudo tee /etc/apt/sources.list
于 2011-08-17T10:20:38.867 に答える
0

手っ取り早く、Python を使用してメモリ内のすべてをバッファリングします。

$ echo two > file
$ echo one | python -c "import sys; f=open(sys.argv[1]).read(); open(sys.argv[1],'w').write(sys.stdin.read()+f)" file
$ cat file
one
two
$ # or creating a shortcut...
$ alias prepend='python -c "import sys; f=open(sys.argv[1]).read(); open(sys.argv[1],\"w\").write(sys.stdin.read()+f)"'
$ echo zero | prepend file
$ cat file
zero
one
two
于 2015-06-05T10:00:23.243 に答える
0
current=`cat my_file` && echo 'my_string' > my_file && echo $current >> my_file

ここで、「my_file」は「my_string」を先頭に追加するファイルです。

于 2010-04-28T16:54:23.483 に答える
0

これは ed の最もクリーンなバリエーションだと思います:

cat myheader | { echo '0a'; cat ; echo -e ".\nw";} | ed myfile

関数として:

function prepend() { { echo '0a'; cat ; echo -e ".\nw";} | ed $1; }

cat myheader | prepend myfile
于 2012-12-29T00:06:56.080 に答える
0

@fluffle のedアプローチが一番好きです。結局のところ、ツールのコマンド ライン スイッチとスクリプト エディター コマンドは本質的に同じものです。スクリプト化されたエディター ソリューションの「クリーンさ」が劣っているとは見なされません。

これは、メッセージをコミットするため.git/hooks/prepare-commit-msgにレポ内ファイルを先頭に追加するために追加されたワンライナーです。.gitmessage

echo -e "1r $PWD/.gitmessage\n.\nw" | ed -s "$1"

.gitmessage

# Commit message formatting samples:
#       runlevels: boot +consolekit -zfs-fuse
#

元のテンプレートのファイルの上に書き込み可能な空の行が残るため、1r代わりに を実行しています。0rthenの上に空行を置かないでください.gitmessage。空行が 2 行になってしまいます。-sed の診断情報の出力を抑制します。

これに関連して、私は vim-buffs のために以下を持っていることも良いことを発見しました:

[core]
        editor = vim -c ':normal gg'
于 2011-08-13T11:01:07.017 に答える
-2

Bah! No one cared to mention about tac.

endor@grid ~ $ tac --help
Usage: tac [OPTION]... [FILE]...
Write each FILE to standard output, last line first.
With no FILE, or when FILE is -, read standard input.

Mandatory arguments to long options are mandatory for short options too.
  -b, --before             attach the separator before instead of after
  -r, --regex              interpret the separator as a regular expression
  -s, --separator=STRING   use STRING as the separator instead of newline
      --help     display this help and exit
      --version  output version information and exit

Report tac bugs to bug-coreutils@gnu.org
GNU coreutils home page: <http://www.gnu.org/software/coreutils/>
General help using GNU software: <http://www.gnu.org/gethelp/>
Report tac translation bugs to <http://translationproject.org/team/>
于 2010-04-16T10:31:04.390 に答える