問題:
bashで使おうと書いた関数をxargs経由で使おうと思ったらできなかった。(BSD系)
<cmd> | xargs <My関数>
# ダメ
<cmd> | xargs -n 1 <My関数>
# ダメ
<cmd> | xargs -I% <My関数> %
だめだったので、ググって解決したのだ。
http://wrist.hatenablog.com/entry/20120603/1338691396
export -f <My関数>
<cmd> | xargs -I% bash -c '<My関数> %'
export
してsh -c
というのは納得です、こう言うことをググらないで考えられるようになりたい!
でもググっちゃう><
追記
以前1行で書こうとして失敗していたが、疑問は氷解したので追記。
以前の失敗事例↓
# 1行にしたら失敗した。そう言うものなんでしょうか...。
export -f <My関数> | <cmd> | xargs -I% bash -c '<My関数> %'
内容としては、パイプラインとサブシェルのよくある話だった。
https://fumiyas.github.io/2013/12/10/lastpipe.sh-advent-calendar.html
失敗理由としては、
メインシェルとサブシェルがあって、パイプラインはサブシェルで実行される事。
そしてbash -c
は新しいプロセスで実行するという事。
ということはつまり、一つ目のexport -f <function>
がサブシェルで行われるとすれば、サブシェルの中でexportされるが、しかしbash -c
で実行される新しいプロセスでは余所のサブシェルがexportした物は当然ながら見れないので、失敗します。
ではどうするかというと、メインシェルの方でexportしておけばよいわけで上述の通りexportしてからパイプラインを実行するという形になるわけですね。
敢えて1行にするのであれば、メインでexportしてからパイプラインを実行すればよいだろうと。
例↓
export -f <My関数> ; <cmd> | xargs -I% bash -c '<My関数> %'
ちなみにこういう時にはプロセス置換も使えるという事が結びついて分かってきたので嬉しい。
<以下、混乱中のこと>
export
はビルトインで、環境変数設定したりするときに使う。
-f
オプションは指定のシェル関数を参照するようにexportする。
ここで、しかし現在のプロセスでシェル関数を呼び出せてるのに、なぜパイプで渡すときにここでexportしないといけないのかわからない。
そうだ、パイプの先はサブシェルになるからか・・・、例えば.bashrcに関数定義をしていた場合はそれはサブシェルには読み込まれないから、事前に環境変数にexportしておけばよいと・・・。
と思って試してみたけど、パイプの先からもシェル関数を呼び出すことができた・・・。サブシェルは元プロセスの変数を参照できるのだから当然と言う感じだ。(xargsを使うとやっぱりできないわけで。)
サブシェルは関係ないのだろうか?
ということは、xargsを使うことの問題だろうか、でも、xargsもサブシェルを起ち上げてるらしいのだが、、、。そんなに特別なサブシェルなのか、なんなのか
ふむ、気になる。
参考
http://171rr.blog.fc2.com/blog-entry-14.html
https://code.i-harness.com/ja/q/a7e61a