3

I understand -i but I don't know how it is different from -I and why the manual says that -i is deprecated. For example what is the difference between using the two lines below:

ls -t | tail -n 4 | xargs -I{} mv {} test2/

ls -t | tail -n 4 | xargs -i mv {} test2/

For the first line can anything ever be subbed into the first {} infront of -I or is that just syntax?

Thanks

terdon
  • 242,166

1 Answers1

10

The reason it is deprecated is because the maintainer(s) of xargs decided it should be deprecated. There's not much more to say there1. These are the relevant sections of man xargs from my Arch system:

       -I replace-str
              Replace occurrences of  replace-str  in  the  initial-arguments
              with  names read from standard input.  Also, unquoted blanks do
              not terminate input items; instead the separator is the newline
              character.  Implies -x and -L 1.
   -i[replace-str], --replace[=replace-str]
          This  option  is  a synonym for -Ireplace-str if replace-str is
          specified.  If the replace-str argument is missing, the  effect
          is  the  same  as  -I{}.  This option is deprecated; use -I in‐
          stead.

So, the only difference between -i and -I is that -i with no arguments is treated like -I{}. The string {} is often used for this kind of thing and has become a convention. For example, find also uses {} in a similar manner in its -exec action:

      -exec command {} +
              This variant of the -exec action runs the specified command  on
              the  selected files, but the command line is built by appending
              each selected file name at the end; the total number of invoca‐
              tions  of  the  command  will  be  much less than the number of
              matched files.  The command line is built in much the same  way
              that xargs builds its command lines.  Only one instance of `{}'
              is allowed within the command, and it must appear at  the  end,
              immediately before the `+'; it needs to be escaped (with a `\')
              or quoted to protect it from interpretation by the shell.   The
              command  is executed in the starting directory.  If any invoca‐
              tion with the `+' form returns a non-zero value as exit status,
              then  find  returns a non-zero exit status.  If find encounters
              an error, this can sometimes cause an immediate exit,  so  some
              pending  commands  may  not  be  run  at  all.  For this reason
              -exec my-command ... {} + -quit may not  result  in  my-command
              actually being run.  This variant of -exec always returns true.

However, this is just a convention, so xargs doesn't force you to use it. You can use anything instead of {} with xargs' -I. For example:

$ seq 5 | xargs -I'&' echo "I read &"
I read 1
I read 2
I read 3
I read 4
I read 5

Or even:

$ seq 5 | xargs -I'a' echo "I read a"
I re1d 1
I re2d 2
I re3d 3
I re4d 4
I re5d 5

So the -i option is either 100% equivalent to -I, when given a string, or is a shorthand for the specific case of -I{}, meaning it tells xargs to use {} as though you had explicitly specified it:

$ seq 5 | xargs -i'a' echo "I read a"  ## as above
I re1d 1
I re2d 2
I re3d 3
I re4d 4
I re5d 5

$ seq 5 | xargs -i echo "I read {}" ## implies -I{} I read 1 I read 2 I read 3 I read 4 I read 5

$ seq 5 | xargs -I echo "I read {}" ## breaks because -I requires a string xargs: I read {}: No such file or directory

Apparently, the maintainer(s) of xargs feel this is no longer a good idea so the option is now deprecated and will presumably be removed from a future version.


1Turns out there is a bit more to say there. Jörg W Mittag pointed out the following in a (now deleted) comment:

Note that it's not just the maintainers of xargs who have decided that. -i was removed from SUSv6 (2004) as well for being "obsolescent". Even -I is not part of SUS core, it is only defined as part of the (optional) XSI extension. So, even the conservative standards authors considered it too ancient, already almost twenty years ago.

terdon
  • 242,166