file
新しいファイルに書き込んで(> newfile
)再移動しなくても()の末尾のバイトを削除できますmv newfile file
。これは以下を介して行われますtruncate
。
truncate -s -1 file
前のバイトを削除できますが、それを移動すると(inodeが変更されます)(一部のtailバージョンの場合):
tail -c +1 file > newfile ; mv newfile file
それでは、ファイルを移動せずにこれを行う方法は?
理想的には切り取りと同様に、非常に大きなファイルの場合でも数バイトだけ変更するだけです。
注:sed -i
ファイルinodeを変更するので、役に立つとしてもこの質問に対する答えではありません(IMO)。
ベストアンサー1
そしてksh93
:
tail -c+2 < file 1<>; file
(リダイレクトされたコマンドが成功すると、最終的にファイルを切り捨てる標準演算子のksh93固有のバリエーション<>;
です。)<>
最初のバイトは削除されます(ファイルの残りの部分をそれ自体に書き、最後の部分を切り取ります)。
以下を使用して同じことを実行できますsh
。
{
tail -c+2 < file &&
perl -e 'truncate STDOUT, tell STDOUT'
} 1<> file
予定ですので参考にしてくださいまれではない希薄なファイル(後で再び穴を掘ることはできますがfallocate -d
)
読み取り/書き込みエラーが発生した場合は、tail
ファイルが部分的に上書きされたままになる可能性があります(たとえば、書き換え後に失敗するabcdefgh
可能性があります)。エラーが発生したときに書き込みオフセットを報告してデータを回復する方法がわかるように、上記の内容を調整できます。まだあります:bcddefgh
bcd
ksh93
unset -v offset
{ tail -c+2 < file || false >#((offset=CUR)); } 1<>; file
$offset
次に、正常に作成されたデータ量を含むifを設定します。
Linux(3.15以降)およびext4またはxfsファイルシステムでは、次のことができます。崩れるfallocate()
システムコールまたはユーティリティのファイルシステムブロックサイズの倍数であるサイズとオフセットまたはバイトの範囲fallocate
。
例えば
fallocate -c -l 8192 file
ファイルの残りの部分を書き換えることなく、ファイルの最初の8192バイトが削除されます(FSブロックサイズが8192の除数であると仮定)。ただし、FSブロックサイズの倍数以外の部分を削除したい場合は役に立ちません。