1

In the documentation for xargs there is mention of a "replstr" that the -I flag takes. I started reading about it when I found this command to run fswatch:

fswatch -0 -e ".*" -i ".rb" . | xargs -0 -n 1 -I {} ruby {}

and started reading the manpage for xargs

-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 255 bytes; this is implemented by concatenating as much of the argument containing replstr as possible, to
        the constructed arguments to utility, up to 255 bytes.  The 255 byte 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. 

Thinking about the term "replstr" is seems like it probably means something like "read evaluate print loop string", is this what it's short for? I started playing around with it to try to get an idea for what {} is doing but I'm not sure I really get it yet:

➜  scripts git:(master) ✗  {0..3}
zsh: command not found: 0..3
➜  scripts git:(master) ✗ echo {0..3}
0 1 2 3
➜  scripts git:(master) ✗ echo {a..3}
a ` _ ^ ] \ [ Z Y X W V U T S R Q P O N M L K J I H G F E D C B A @ ? > = < ; : 9 8 7 6 5 4 3
➜  scripts git:(master) ✗ echo {a..d}
a b c d
➜  scripts git:(master) ✗ echo cats and dogs | xargs
cats and dogs
➜  scripts git:(master) ✗ echo cats and dogs | xargs {}
xargs: {}: No such file or directory
➜  scripts git:(master) ✗ echo cats and dogs | xargs {} echo {}
xargs: {}: No such file or directory
➜  scripts git:(master) ✗ echo cats and dogs | xargs -I {}

➜  scripts git:(master) ✗ echo cats and dogs | xargs -I {} echo {}
cats and dogs

For example echo {a..3} really doesn't make sense to me. It definitely seems like it's doing something to the effect of "substitute this list of strings here" but I'm not sure if that's the right way to look at it. Also I'm not sure if {} is a specfic type of replstr and if there's more or if a replstr is just anything in between a pair of curly braces. Would love some guidance on replstr's and how to approach them.

1
  • 1
    "replstring" == "replace string", e.g., the placeholder that xargs will replace when generating command lines.
    – larsks
    Oct 23, 2016 at 1:41

3 Answers 3

4

replstr means "replacement string" or "replace string".

The original replstr is {}. It was first introduced with the find command exec clause where it replaced by each filename found, e.g.

find /tmp -name "foo*" -exec echo file {} found \;

will display, assuming two files match the pattern:

file foo1 found
file foo2 found 

The xargs command allows to do the same with arguments built from strings passed to its standard input, and also allows to specify something different than {} as replacement string.

Note that the default replstr is just {} with nothing inside the curly brackets, the latter being used for different purposes, e.g. ranges as you already noticed or parameter expansion.

2

The -I argument works like this: -I whatever means that occurrences literally of whatever are replaced by the command argument. Demo:

$ echo "a
b
c" | xargs -I f echo hey f hey f
hey a hey a
hey b hey b
hey c hey c

See? xargs took each of the lines a, b, and c, and substituted them in place of f in echo hey f hey f.

There is no {} involved.

The -I option is POSIX. GNU xargs documents a deprecated -i option which, if invoked as -iwhatever behaves like -I whatever. If invoked as just -i it behaves like -I {}. In this case, occurrences of {} are replaced. {} is clearly inspired by a feature of find: its -exec predicate.

The {a..b} and foo{a,b,c}bar Bash syntax processed by its "brace expansion". {} has no special meaning and is passed to a command as-is. (If it weren't, it would break standard-conforming, commonly occurring find invocations.)

1

The {...} is the shell's brace expansion, which supports lists like {a,b,c} (expands to a, b and c), and sequences of numbers like {0..13} (expands to the numbers 0, 1... 12, 13) or characters {a..d} (a,b,c,d). (Brace expansion has nothing to do with the {} placeholder used by xargs).

The somewhat odd sequence that {a..3} expands to is explained by the ASCII character table. As a isn't a number, both are taken as characters, and the expansion is all the characters between a and 3 by the character codes' numerical value. As it happens, a comes after 3, so the sequence does downwards through the uppercase letters and the numbers 9 to 3.

As seen, mixing letters and numbers in a range like that isn't very useful, but {a..z} or {A..Z} might be, as well as the similar [a-z] and [A-Z] in regexes and shell globs. (That is, if you can ignore the rest of the letters.)

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .