cmd
2行のテキストを実行して出力します。
$ cmd
foo
bar
これを `/long/path/x.{load,conf} に書く必要があります。
このターゲットに書き込むには、手動で操作できないスーパーユーザー権限が必要です。
$ echo "foo" > /long/path/x.load
$ echo "bar" > /long/path/x.conf
〜のように「コマンドが開始され、権限を取得する前にリダイレクトが完了します。」
これを考えると扱いにくいテキスト文字列のプレースホルダなfoo
ので、bar
これを行うには良い方法は何ですか?
実際、私は多くの頭痛を引き起こさない解決策を探しています。これは一連のガイドラインの1つのステップを表し、説明を必要としないコードを書くことをお勧めしますが、常に可能なすべての方法に興味があります。小さなことをするために。
答え1
Awkのリダイレクト演算子はここで便利です。このトピックにはいくつかのバリエーションがあります。
cmd | sudo awk '{print >"/long/path/x." (NR==1 ? "load" : "conf")}'
cmd | sudo x=/long/path/x awk 'NR==1 {print >ENVIRON["x"]".load"}
NR==2 {print >ENVIRON["x"]".conf"}'
cmd | sudo awk 'FNR==1 && NR!=1 {exit} {print >ARGV[NR-1]}' - /long/path/x.{load,conf}
最初は最も短くて簡単です。各行は、演算子の後にある式を評価することによって決定されたファイル名で印刷されます>
。現在の行番号NR
はファイル名を計算するために使用されます。式の連結は awk の文字列連結演算子です。
答え2
人々は通常これを行いますtee
:
cmd | sudo tee /long/path/x.{load,conf}
tee
名前付きすべての出力ファイルに入力コピーを書き込みます。同様に、exec
中括弧拡張の引数が生成される前にリダイレクトが発生します。したがって、上記のコードは正しく機能し、結果のファイル名と標準出力をすぐに作成する必要があります。
tee
データのコピー中に端末に記録された内容を表示したくない場合は、標準出力を次にリダイレクトできます。/dev/null
これはsudo
そのリダイレクトを妨げません。
記録されているように、tee
出力ファイルは記録される前に切り捨てられます。追加するには、-a
保留スイッチを追加し、tee
名前付きのすべての出力ファイルの末尾に入力データをコピーします。
もちろん、各行を異なる場所に書き込むのは少し難しいです。しかし、儀式コマンドをsed
提供します。w
これを-e
式引数と組み合わせると、中括弧拡張を使用してスクリプト全体を作成できますsed
。
cmd | sudo sed -e'$x;/./w '/long/path/x.{load,conf}$'\n1x'
...w
最初の行を最初のパラメータファイルに書き込み、2行目を2番目のパラメータファイルに書き込みます。 e の変更は、x
単に 1 行目と 2 行目のスクリプトのバランスをとり、2 行が 1 行につき 2 つのファイルsed
に書き込まれるのを防ぎます。
私はこれを次のようにテストしました。
printf %s\\n 1 2 |
sed -e'$x;/./w '/tmp/{1,2}$'\n$!x'
...そして逃げました...
head /tmp/[12]
...印刷...
==> /tmp/1 <==
1
==> /tmp/2 <==
2
答え3
コマンドからファイル設定cmd
まで、すべてをスクリプト化するソリューションが必要かどうかはわかりませんが、そのファイル設定に応じてまだsudoを使用して実行できますが、リダイレクトする必要があります。.load
.conf
ストゥッド注文する:
$ sudo sh -c "echo 'foo' > /long/path/x.load"
$ sudo sh -c "echo 'bar' > /long/path/x.conf"
ここでは、sudo
より高い権限を取得し、sh
シェルを実行します。これにより、指定されたコマンドが解釈され、その瞬間にのみリダイレクトが発生し、権限の問題は発生しません。
偶然にこのスクリプトを作成する必要がある場合は、特定の要件に応じて次のように見えることがあります。
cmd | {
read line
sudo sh -c "echo '$line' > /long/path/x.load"
read line
sudo sh -c "echo '$line' > /long/path/x.conf"
}