BSD版xargsの -I オプションで長い文字列を置換する場合は -S で replsize の設定が必要

久しぶりなので小ネタ。

環境

なにごと?

いつものように xargs -I でコマンドを置換して諸々やっていたのですが、あるときなぜかうまく置換されないことがあったのです。

これは期待どおり。

$ echo 'short' | xargs -I@ echo '[@]'
[short]

しかし xargs に渡す値が長くなると置換されず、 -I で指定した文字がそのまま出てきてしまう…。

$ echo 'looo(中略)ooong' | xargs -I@ echo '[@]'
[@]

調べてみる

というわけで man を見てみると…

$ man xargs

XARGS(1)                  BSD General Commands Manual                 XARGS(1)

NAME
     xargs -- construct argument list(s) and execute utility

SYNOPSIS
     xargs [-0oprt] [-E eofstr] [-I replstr [-R replacements] [-S replsize]]
           [-J replstr] [-L number] [-n number [-x]] [-P maxprocs] [-s size]
           [utility [argument ...]]
(中略)
     -I replstr
             Execute utility for each input line, replacing one or more occurrences of replstr in up to replacements (or 5 if no -R flag is specified) arguments to utility with the entire line of input.  The
             resulting arguments, after replacement is done, will not be allowed to grow beyond replsize (or 255 if no -S flag is specified) bytes; this is implemented by concatenating as much of the argument
             containing replstr as possible, to the constructed arguments to utility, up to replsize bytes.  The size limit does not apply to arguments to utility which do not contain replstr, and furthermore,
             no replacement will be done on utility itself.  Implies -x.

     -S replsize
             Specify the amount of space (in bytes) that -I can use for replacements.  The default for replsize is 255.

つまり -I で置換する値は replsize のサイズ(単位はバイト)を超えてはダメでデフォルトは 255 バイト、変更するには -S オプションを使えばOK。

解決

というわけで、今回のやつはこんな感じでサイズ指定すればよいのでした。

$ echo 'looo(中略)ooong' | xargs -S1024 -I@ echo '[@]'
[loooooooooo ... oooooooooooong]

ちなみにそのへんのLinuxに入っているGNU版xargsだと -S オプションとかは無い様子。