xargsにbashのfunctionを渡す方法
あっさりできるかと思ったら意外に時間が掛かってしまったので纏めておく。
ポイントは2点で、
- export -f 関数名 しておく
- xargsではbash -c "コマンド" を実行する
で行けた。
例
パスにそのbasenameした結果をTAB区切りで連結しただけの文字列をechoする関数を定義する。
$ function echo_with_basename(){ > echo -e "$1\t`basename $1`" # -eオプションが無いと\tがTABに変換されない > }
この関数を次のようにファイルリストを出力した結果をパイプで繋ぎxargsに渡す。
$ cat filelist.txt /home/wrist/data/A00000.txt /home/wrist/data/A00001.txt /home/wrist/data/A00002.txt /home/wrist/data/A00003.txt /home/wrist/data/A00004.txt $ cat filelist.txt | xargs -I % echo_with_basename % # "-I %"のオプションは引数を%で表すことを示す xargs: echo_with_basename: そのようなファイルやディレクトリはありません
このようにそのようなファイルやディレクトリが無いと言われてしまう。
そこでexport -fした上で次のように実行する。
$ export -f echo_with_basename $ cat filelist.txt | xargs -I % echo_with_basename % xargs: echo_with_basename: そのようなファイルやディレクトリはありません
またしても同じ事を言われてしまう。これを防ぐためには、次のように実行する。
$ cat filelist.txt | xargs -I % bash -c "echo_with_basename %" /home/wrist/data/A00000.txt A00000.txt /home/wrist/data/A00001.txt A00001.txt /home/wrist/data/A00002.txt A00002.txt /home/wrist/data/A00003.txt A00003.txt /home/wrist/data/A00004.txt A00004.txt
これで所望の結果が得られた。
なおインタラクティブシェルだけでなくスクリプトとして実行する際もexport -fした上で同様に利用することができる。
参考
http://stackoverflow.com/questions/3321738/shell-scripting-using-xargs-to-execute-parallel-instances-of-a-shell-function
http://www.webzoit.net/hp/it/internet/homepage/env/cs/server/os/type/unix/linux/shell/kind/sh_bash/function2/
http://stackoverflow.com/questions/979453/how-can-i-use-aliased-commands-with-xargs