(wrist blog)

twitterはこちら http://twitter.com/wrist

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した上で同様に利用することができる。