ルートが所有するファイルの最後の行を削除します。

ルートが所有するファイルの最後の行を削除します。

666ユーザーが別のスクリプトを使用して編集できる権限を持つファイルがあります。これはうまくいきます。ファイルの最後の行を削除するスクリプトを作成する必要がありますが、sedtrisのようなものを使用して最初にファイルを作成してその場所に移動するのと同じようには機能しません。ユーザーはこれを行うことはできません。

新しいファイルをその場所に移動せずにファイルを編集して最後の行を削除する方法はありますか?

答え1

この質問にタグが付けられたので、エディタを使用してファイルを内部で編集する方法は次のとおりですed

printf '%s\n' d w q | ed -s file

を使用して編集セッションを開始すると、edエディタは常に開いているファイルの最後の行にユーザーを配置します。ファイルの最後の行を削除するには、削除できます。現在のlineを使用してd変更されたバッファをファイルに書き換えてからw終了しますq。ほとんどのエディタの実装ed(BusyBoxを除く)では、次の代わりにed非標準の組み合わせコマンドを使用できます。wqwq

これは新しいファイルを生成しません(結果ファイルは元のファイルと同じinode番号を持ちます)。

答え2

その場で切り取ることができます。 GNUシステムでは:

truncate -s -"$(tail -n1 file | wc -c)" file

truncate -<n>刈る<n>ファイルの末尾にあるバイトです。ここ<n>返された最後の行の長さ(バイト単位)で計算されますwc

移植可能な場合は、次のように切り取ることがperlできます。

tail -n1 file | perl -ne '
  if (seek(STDOUT, -length, 2)) {
    truncate STDOUT, tell STDOUT or die "truncate: $!\n"
  } else {
    die "seek: $!\n"
  }' 1<> file

ファイルの内容を書き換えないため、sedベースの方法よりも効率的です(テキスト以外のファイルやファイルシステム全体に直面しても安全です)。

答え3

これを確認して、通常のsedコマンドの出力をユーザーのローカルファイル(一時ファイル)に送信し、そのファイルを関連ファイルに出力に送信します。

sed '$d' /path/to/file > ./tempfile; cat ./tempfile > /path/to/file

答え4

一時ファイルを生成せずにsedで "w"コマンドを使用してこれを行う方法があります。これにより、ファイルの inode 番号は変更されません。特に、スクリプトで使いやすいより良いバージョンB)は、まずファイル名を変数に割り当てることです。

A) cat file|sed -ne '1h;${x;wfile' -e '};1!H'
B) file="test.txt";cat "$file"|sed -ne '1h;${x;w'"$file" -e '};1!H'

sedが変更したいファイルから直接入力を読み取るのではなく、パイプから入力を読み取ることができるように、ファイルはcatに渡されます。 sedによって読み取られた各入力行は、予約されたスペースに保存されます。ただし、入力が終わると、最後の行が保存される前にスペースが予約され、ファイルに書き込まれます。

関連情報