ファイルを開いたり生成したり、その中にループでたくさんの行を書きたいです。
基本的に私はそうします:
for i in {1..100}; do
echo "line $i">>test.log
done
私の理解は、OSがtest.log
ファイルi
時間を開いたり閉じたりすることです。
私は別の構文/アプローチを見つけました。
exec {log}>>test.log
for i in {1..1000}; do
echo "line $i" >& $log
done
{log}>&-
すでに開いているファイルの使用
exec {log}>>test.log
中にファイルを開いたり作成したり、開いたままにしたいとしますか?ファイルハンドルが閉じますか?echo "line $i" >& $log
{log}>&-
この方法は何ですか?ユースケースの詳細情報はどこにありますか?
答え1
表示されたユースケースでは、for
複合コマンドの標準出力をリダイレクトできます。これにより、ファイル記述子を処理する必要がなくなります。
for i in {1..100}; do
printf 'line %d\n' "$i"
done >test.log
これにより、名前付きファイルが作成または切り捨てられ、test.log
ループ内の標準出力ストリームのすべての出力(他の場所で明示的にリダイレクトされない限り)はそのファイルに移動されます。>>
ファイルを切り捨てるのではなく、ファイルに追加するために使用されます。ファイルは一度だけ開きます。
他の複合コマンドでも同じことができます。
if [ -e file ]; then
echo 'file exists'
else
echo 'file does not exist'
fi >out.log
{
echo 'line 1'
cat some-file
echo 'last line'
} >lines.txt
答え2
まず、fdは単一ループ内でのみ使用されるため、後で手動で閉じる必要なくループにリダイレクトを適用することも可能です。
for i in {1..100}; do
echo "line $i"
done >>test.log
ここでループの先頭からファイルを消去するには、追加のリダイレクトを使用するのではなく、切り捨てリダイレクトを使用することも> test.log
できます。>>
ループ全体に対して同じファイルハンドルなので、ループ反復間で切り捨てられません。
exec
リダイレクトの処理に使用する特定の名前があるかどうかはわかりません。これは、シェル全体に適用されるリダイレクトを変更する方法です。もう少し奇妙なことは、別の使用法がexec
シェル全体を置き換えるコマンドで使用されることです。ただし、ここではシェルは引き続き実行されます。
1つは{var}>filename
非標準拡張です。Bashのマニュアルに記載されている:
各リダイレクトの前にファイル記述子を含めることができますが、次の形式の単語が先頭になることもあります。変数名}。この場合、>&-と<&-を除くすべてのリダイレクト演算子に対して、シェルは10より大きいファイル記述子を割り当て、{変数名}。 >&-または<&-の前に{がある場合変数名}、varname値は閉じるファイル記述子を定義します。もし{変数名指定した場合、リダイレクトはコマンドの範囲外で持続するため、シェルプログラマーはファイル記述子の寿命を手動で管理できます。
また、少なくともkshとzshでサポートされています(Bashのためにそれらの1つから借りることができます)。
自動割り当ては必要ありませんが、固定金額を使用できます。たとえば、次のようになります。
exec 9>>test.log
for i in {1..100}; do
echo "line $i" >&9
done
exec 9>&-
fd番号を直接追跡するだけです。 3から9までの数字は、スクリプト作成者が自由に使用できる必要があります。 0、1、2 は標準ファイル記述子で、10 以上はシェルで内部で使用できます。