
ファイルの最後の50行を維持し、毎分温度を保存してみました。私は次のコマンドを使用しました。
tail -n 50 /home/pi/Documents/test > /home/pi/Documents/test
しかし、結果は空のテストファイルです。私はそれがテストファイルの最後の50行をリストし、それをテストファイルに挿入すると想像しています。このコマンドを使用するとき:
tail -n 50 /home/pi/Documents/test > /home/pi/Documents/test2
うまくいきます。 test2ファイルには50行があります。
誰でも問題が何であるかを説明できますか?
答え1
問題は、シェルがコマンドを実行する前にコマンドパイプラインを設定することです。 「入力と出力」の問題ではなく、tailが実行される前にファイルの内容が消えることです。次のように進みます。
- シェルは書き込み用
>
に出力ファイルを開き、それを切り捨てます。 - シェルは、この出力に対してファイル記述子 1 (標準出力用) を設定します。
- シェルの実行
tail
。 tail
実行して開き、/home/pi/Documents/test
何も探さないでください。
多くの解決策がありますが、鍵は問題を理解し、正確に何が間違っているのか、その理由は何であるかを理解することです。
それからあなたが探しているものが出てきます。
echo "$(tail -n 50 /home/pi/Documents/test)" > /home/pi/Documents/test
説明する:
$()
コマンド置換と呼ばれる実行tail -n 50 /home/pi/Documents/test
- 引用符は出力の改行を維持します。
> /home/pi/Documents/test
出力をecho "$(tail -n 50 /home/pi/Documents/test)"
同じファイルにリダイレクトします。
答え2
ファイルリダイレクトファイルを最初に消去するもう1つの解決策は、次をsponge
使用することです。moreutils
次のように梱包してください。
tail -n 50 /home/pi/Documents/test | sponge /home/pi/Documents/test
答え3
これは、bashが最初にリダイレクトを処理して>
ファイルの内容を削除するためです。その後、コマンドを実行します。を使用すると、>>
最後の50行がファイルの現在の内容の末尾に追加されます。この例では、同じ50行が2回繰り返されます。
別のファイルにリダイレクトされると、コマンドは期待どおりに機能します。以下は、ファイルの最後の50行を同じ名前のファイルに書き込む1つの方法です。
tail -50 /home/pi/Documents/test > /home/pi/Documents/test2 && mv /home/pi/Documents/test2 /home/pi/Documents/test
まず、最後の50行を一時ファイルに書き込み、それを移動して元のmv
ファイルを置き換えます。
コメントで指摘したように、ファイルがまだ開いている場合は機能しません。ファイルを移動すると、新しいinodeが作成され、所有権と権限が変更される可能性があります。一時ファイルを使用してこれを行うより良い方法は次のとおりです。
tail -50 /home/pi/Documents/test > /home/pi/Documents/test2 ; cat /home/pi/Documents/test2 > /home/pi/Documents/test
一時ファイルも削除できますが、削除されるたびにその内容が上書きされます。
答え4
これでシェルリダイレクトの主な問題を理解したので、ファイルを最後の50行に切り捨てる別の方法があります。
file=/path/to/the/file
n=$(( $(wc -l < "$file") - 50 ))
[[ $n -gt 0 ]] && sed -i 1,${n}d "$file"
この困難な作業は、-i
(GNU)sedの「所定の位置で編集」機能によって行われます。この機能は、一時ファイルに出力を生成することで、後から機能します。残りの行は sed 操作の数学を設定します。つまり:
- ファイル()の行数を数えて
wc
50を減算しますn
。 - 正の場合、
n
sed コマンドを実行して行 1 から n までを削除します。