回答:
ed代わりに試してください:
ed <<< $'1d\nwq' large_file
その「大きい」とは、約1,000万行以上を意味する場合、より適切に使用しますtail。インプレース編集はできませんが、そのパフォーマンスにより、その不足が許されます。
tail -n +2 large_file > large_file.new
編集して、時差を表示します。
(awk同じマシン(CPU 2.2GHz)での実行時間を持つためにJaypalによるコードが追加されました。)
bash-4.2$ seq 1000000 > bigfile.txt # further file creations skipped
bash-4.2$ time sed -i 1d bigfile.txt
time 0m4.318s
bash-4.2$ time ed -s <<< $'1d\nwq' bigfile.txt
time 0m0.533s
bash-4.2$ time perl -pi -e 'undef$_ if$.==1' bigfile.txt
time 0m0.626s
bash-4.2$ time { tail -n +2 bigfile.txt > bigfile.new && mv -f bigfile.new bigfile.txt; }
time 0m0.034s
bash-4.2$ time { awk 'NR>1 {print}' bigfile.txt > newfile.txt && mv -f newfile.txt bigfile.txt; }
time 0m0.328s
awkし、次の結果を得た-[jaypal:~/Temp] seq 1000000 > bigfile.txt [jaypal:~/Temp] time awk 'NR>1 {print}' bigfile.txt >newfile.txt real 0m0.649s user 0m0.601s sys 0m0.033s
awkのパフォーマンスがに近づくと予想していましたsed。(自分への注意:期待しないでください-代わりにテストしてください。)
tail -n +2 bigfile.txt > bigfile.new && mv -f bigfile.new bigfile.txt;。複数のプロセスで使用される単一のタスクリストを追跡するために、ロック付きの単一のファイルを使用しています。最初のポスターで使用したものから始めましたsed -i 1d large_file 。そのため、ファイルが1〜2秒間ロックされていました。tail/mvコンボはほぼ瞬時に完了します。ありがとうございました!
ファイルの先頭から物事を効率的に削除する方法はありません。最初からデータを削除するには、ファイル全体を書き直す必要があります。
ただし、ファイルの末尾から切り捨てるのは非常に高速です(OSはファイルサイズ情報を調整するだけで、現在使用されていないブロックをクリアすることができます)。通常、ファイルの先頭から削除しようとすると、これは不可能です。
ブロック/エクステント全体を正確に削除した場合、理論的には「高速」になりますが、そのためのシステムコールがないため、ファイルシステム固有のセマンティクス(存在する場合)に依存する必要があります。(または、ファイルの実際の開始を示すために、最初のブロック/エクステント内に何らかの形のオフセットを持っていると思います。それも聞いたことがないでしょう。)
最も効率的な方法、それをしないでください!どちらにしても、ディスク上に2倍の「大きな」スペースが必要になり、IOが無駄になります。
1行目なしで読みたい大きなファイルが残っている場合は、1行目を削除するために読み込む必要があるまで待ちます。ファイルをstdinからプログラムに送信する必要がある場合は、tailを使用して送信します。
tail -n +2 | your_program
ファイルを読み取る必要がある場合は、ディスクに必要なスペースがある場合に限り、1行目を削除することができます。
tail -n +2 | tee large_file2 | your_program
stdinから読み取れない場合は、fifoを使用します。
mkfifo large_file_wo_1st_line
tail -n +2 large_file > large_file_wo_1st_line&
your_program -i large_file_wo_1st_line
bashを使用している場合は、プロセス置換の利点を活用してください。
your_program -i <(tail -n +2 large_file)
ファイルを探す必要がある場合、そもそもファイルにこだわるよりも良い解決策はありません。このファイルがstdoutによって生成された場合:
large_file_generator | tail -n +2 > large_file
そうでない場合は、常にfifoまたはプロセス置換ソリューションがあります。
mkfifo large_file_with_1st_file
large_file_generator -o large_file_with_1st_file&
tail -n +2 large_file_with_1st_file > large_file_wo_1st_file
large_file_generator -o >(tail -n 2+ > large_file_wo_1st_file)
tail、私はむしろ実行する時間カウントします両方の最初の行を削除し、交換するbigfile.txtとしbigfile.new。