2

I have the following command that checks if any new files are added and automatically calls svn add on all these files

svn status | grep -v "^.[ \t]*\..*" | grep "^?" | awk '{print $2}' | xargs svn add

But when there are no files, svn add results in a warning.

How to stop from xargs from getting called the previous command doesn't result in any values? The solution needs to work with both GNU and BSD (Mac OS X) versions of xargs.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Sudar
  • 18,954
  • 30
  • 85
  • 131
  • 2
    The POSIX standard for [`xargs`](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/xargs.html) (building on the de facto implementations of `xargs` before the standard was set) requires the command to be executed once even if there are no file names. Only the GNU version seems to recognize the … idiocy? … nuisance factor of that requirement. If your code has to work on platforms with and without GNU `xargs` without installing GNU `xargs`, then you're going to have to work hard. – Jonathan Leffler Sep 15 '13 at 16:12

4 Answers4

16

If you're running the GNU version, use xargs -r:

--no-run-if-empty  
-r
   If the standard input does not contain any nonblanks, do not run the command.
   Normally, the command is run once even if there is no input. This option
   is a GNU extension.

http://linux.die.net/man/1/xargs

Adam Liss
  • 47,594
  • 12
  • 108
  • 150
  • Thanks. But unfortunately, I need this script to work both in GNU and BSD (Mac) version. – Sudar Sep 15 '13 at 15:23
1

If you're using bash, another way is to just store outputs in arrays. And run svn only if the there is an output.

readarray -t OUTPUT < <(exec svn status | grep -v "^.[ \t]*\..*" | grep "^?" | awk '{print $2}')
[[ ${#OUTPUT[@]} -gt 0 ]] && svn add "${OUTPUT[@]}"
konsolebox
  • 72,135
  • 12
  • 99
  • 105
0

I ended up using this. Not very elegant but works.

svn status | grep -v "^.[ \t]*\..*" | grep "^?" && svn status | grep -v "^.[ \t]*\..*" | grep "^?" | awk '{print $2}' | xargs svn add
Sudar
  • 18,954
  • 30
  • 85
  • 131
0
ls /empty_dir/ | xargs -n10 chown root   # chown executed every 10 args
ls /empty_dir/ | xargs -L10 chown root   # chown executed every 10 lines
ls /empty_dir/ | xargs -i cp {} {}.bak   # every {} is replaced with the args from one input line
ls /empty_dir/ | xargs -I ARG cp ARG ARG.bak # like -i, with a user-specified placeholder

https://stackoverflow.com/a/19038748/1655942

Community
  • 1
  • 1
arielCo
  • 413
  • 5
  • 16
  • Although the last 2 examples work (and allow for repeated substitution of the item to be processed), they will execute the command for every single item in the list (because of the implied `-L 1`), which could mean a performance hit when processing large lists. – ack Mar 27 '16 at 21:12