xargsでエラー {} does not exist

xargsを使っているときに以下のようなエラーが出た

cp: directory /tmp/{} does not exist

原因は-Iのオプションを使った状態で、引数全体が255 bytesを超えてしまったこと。どうやらBSDのxargsだと255 bytesは超えられないという制約がある模様(GNUの場合はhelpを見てもその制約が書いてなかった)

今回は確かにxargsの引数部分がかなり長かったので、関数化して使うことで短くなるようにした。

もともとがこんな感じ

$ cat file | xargs -n1 -I{} -P8 bash -c "find $from -maxdepth 3 -name \"{}*\" | shuf | head -n $count | xargs -I@ cp @ $to/{}/"

ちなみにやっていることは、fileに含まれるprefixで始まるfromディレクトリ中のファイルを最大でcount数分だけランダムにtoディレクトリにコピーする、というもの

以下のように関数化して使うことで255 bytesを超えないようになった

function copy()
{
    prefix=$1
    from=$2
    to=$3
    count=$4
    find $from -maxdepth 3 -name "${prefix}*" | shuf | head -n $count | xargs -I{} cp {} $to/$prefix
}
export -f copy
cat file| xargs -n1 -I{} -P8 bash -c "copy {} $from $to $count"

注意点としては

  • export -fで関数を別のシェルからも見えるようにすること
  • 関数を呼ぶ部分をbashの引数として書くこと

の2つ

xargsにbashのfunctionを渡す方法 - (wrist blog)