これは非常にマイナーで近い答えをたくさん見つけましたが、それでも理解できません。デフォルトでは、次のパラメータを使用してスクリプトを作成しました。
var1=$1
echo "outside the pipe, my variable is set: $var1"
ls *.* | xargs sh -c 'echo "$0" "$@"; echo "inside the pipe, my variable is empty: $var1"'
私の問題は、私の変数の1つでファイル名のリストをパイプする必要があることです。どうすればいいですか?ファイルのリストを配列に書き込み、パラメータを追加/前に追加してパイプに渡そうとしましたが、後でチャンクとして処理すると問題が発生します。元のスクリプトは次のとおりです(imagemagick)。
ls *.png | xargs -n 100 sh -c 'convert "$0" "$@" -evaluate-sequence $var1 ../out2/"$0"'
どんな助けでも大変感謝します!
ベストアンサー1
いいえ、ファイル名のリストをパイプする必要はありません。
var1=$1
find . -maxdepth 1 -type f -name '*.png' -exec sh -c '
var1=$1; first=$2; shift 2
convert "$first" "$@" -evaluate-sequence "$var1" ../out2/"$first"' sh "$var1" {} +
つまり、内部サブシェルを$var1
最初の引数として使用します(0番目の引数はシェルの名前でなければなりません)。
$var1
内部シェルは引数のリストを削除し、見つかったfind
最初のパス名に対して同じことを行います(理由はわかりませんが、少なくともコードが実行していると思うのと同じにします)。それ$@
からshift 2
。
100単位でこれを行う必要がある場合:
var1=$1
find . -maxdepth 1 -type f -name '*.png' -print0 |
xargs -0 -n 100 sh -c '
var1=$1; first=$2; shift 2
convert "$first" "$@" -evaluate-sequence "$var1" ../out2/"$first"' sh "$var1"
これがパイプ出力よりも安全な理由は、パスls
名が改行で終わるリストではなくヌルで終わるリストに渡されるためです。スクリプトsh
は両方のバリエーションと同じで、$var1
コマンドライン引数として提供されます。
コードが機能しない理由は、シェルが親シェルで何が起こっているのかsh -c
わからないからです。$var1
関連: