いくつかのディレクトリツリーを作成し、ツリーの各端にランダムな内容を含むテキストファイルを埋めたいです。
これまでに試したことは次のとおりです。
#!/bin/bash
set -e
echo "Generating test folders"
mkdir -p ./parent_{0..9}/child_{0..9}
head -c 100 /dev/urandom | xargs echo >> ./parent_{0..9}/child_{0..9}/test.txt
echo "done"
実行すると、次のエラーが発生します。
./gen-test.sh: line 8: ./parent_{0..9}/child_{0..9}/test.txt: ambiguous redirect
私が間違っていて、これを行うより賢い方法は何ですか?
答え1
あなたが間違っていることがうまくいかないのは、リダイレクトとファイル名の生成がxargsではなくシェルによって処理されるためです。
書くとき
foo > foo.out
その後、シェルがfoo
実行され、標準出力をキャプチャしますfoo.out
。
走れば
foo | xargs bar > bar.out
その後、シェルがfoo
自動的に実行され、標準出力をキャプチャしてxargs
標準出力foo
をxargs
。ある時点で実行され、標準入力として受け取ったデータは引数として渡され、結果のxargs
標準出力がの標準出力と区別されないbar
ように実行されます。シェルはこの標準出力をキャプチャして記録します。bar
xargs
bar.out
あなたの引数は./parent_{0..9}/child_{0..9}/test.txt
シェルでも解釈されます。パラメータを削除してパターンで生成されたファイル名に置き換えることで、mkdir
コマンドラインは次のようになります(...
簡潔にするために追加)。
mkdir -p ./parent_0/child_0/test.txt ./parent_0/child_1/test.txt ./parent_0/child_2/test.txt ... ./parent_1/child_0/test.txt ... ./parent_9/child_9/test.txt
後で逃げました。
head -c 100 /dev/urandom | xargs # ...
echo
つまり、100バイトの任意のデータを読み取り、それをコマンドライン引数に変換してからそのxargs
データを出力しようとするという意味です(バイナリデータであり、ここではコマンドについて話しているのでうまく進まないでしょう)。
最後に、シェルはそれを見て、>>
同じパターンが続く追加されたリダイレクトとして解釈します。
>> /parent_0/child_0/test.txt /parent_0/child_1/test.txt # and so on
しかし、そうすることはできません。一度に1つのファイルにのみリダイレクトできます。これは「あいまいなリダイレクト」エラーです。
最も簡単な解決策は、ファイルを繰り返すことです。
for file in /pattern_0/child_0/test.txt; do
head -c 100 /dev/urandom > $file
done
xargsを使用するすべてのソリューションは、コマンドライン引数を標準出力に変換するためにechoを必要とし、xargsを使用して同じ標準出力をコマンドライン引数に戻すことができるので、これは確かに非効率的です。