Example xargs -x option in action

GNU xargs has the '-x' option. The manual page says:

-x Exit if the size (see the -s option) is exceeded.

But xargs doesn't seem to care if the -x value is set or not. I could not make an example in which -x has no effect whatsoever.

Please provide two examples in which the only distinguishing feature is the added -x and yields a different result.

+4
source share
3 answers

You need to set the size to check if you have exceeded it.

 $ echo -e "12\n1234" 12 1234 $ echo -e "12\n1234" | xargs echo 12 1234 $ echo -e "12\n1234" | xargs -x echo # no effect 12 1234 $ echo -e "12\n1234\n13" | xargs -s 8 echo # process valid args until an error occurs xargs: argument line too long 12 $ echo -e "12\n1234" | xargs -s 8 -x echo # error and exit xargs: argument line too long 
+4
source

I still cannot explain why this gives 1 - 11:

 (seq 11; echo -e "1234111";seq 12 15) | xargs -s 11 echo 

but it gives 1 - 9:

 (seq 11; echo -e "1234111";seq 12 15) | xargs -s 11 -x echo 

Will -x always give only the difference in one line (namely, in a line that would be too long)?

It depends, of course, on the type of xargs that you use, but the common GNU findutils' xargs (which may well be the one you have) has just this behavior, violating the principle of least surprise: It accumulates the command line in memory by reading it again of the next input element and adding it to the existing command line until it matches the length of the line ... Now it checks if the reading element will not fit into the line as one argument (which is the case with echo 1234111 in your example ):

  if (p >= endbuf) { exec_if_possible (); error (EXIT_FAILURE, 0, _("argument line too long")); } 

(the above code is closer to the end of the read_line() function in findutils-4.6.0 / xargs / xargs.c, almost the same in findutils-4.4.2)

 static void exec_if_possible (void) { if (bc_ctl.replace_pat || initial_args || bc_state.cmd_argc == bc_ctl.initial_argc || bc_ctl.exit_if_size_exceeded) return; bc_do_exec (&bc_ctl, &bc_state); } 

Here, where the -x option (corresponding to bc_ctl.exit_if_size_exceeded ) matters - with -x , exec_if_possible() simply return without bc_do_exec() with a well-formed command already accumulated ( echo 10 11 in your example). Then, after returning, the error() function exits the xargs program.

I expected 12 to 15 years in one of them.

Since the specified xargs always exits if the input element is too long on its own, all of the following elements are lost.

+1
source

TL; DR

  • Using -x makes sense only with the arguments -n <argumentCount> : <argumentCount> , if available, should be placed on the same command line , either based on the maximum maximum number of bytes, or with the explicit option -s <byteCount+1> ; if not, xargs fails.
    Without -x a command line with fewer arguments will be built, and no error will occur - if only one argument does not fit - see the next point.

    • Note that the -x logic is implicitly applied to the -L <lineCount> and -I <placeHolder> .
    • Warning. As for OSX 10.11.3 and PC-BSD 10.1, the combination of -x and -n seems to be broken in the BSD xargs implementation - see below.
  • Without -n there is no reason to use -x , since both xargs implementations always fail when they encounter a single argument that will result in a command that is too long for the total byte size (again, implied or indicated with -s <byteCount+1> ).

    • GNU xargs : -x without -n causes an error (starting with version 4.2.2), as found in the Armali hepful answer .
    • BSD xargs : -x without -n not syntactically supported .
    • A simple example that shows for both implementations that even without -x one too long argument causes an error:
      • $ echo 1 10 | xargs -s 7 echo # max. command length is 6 (7 - 1) bytes 1 # ok: 'echo 1' is 6 bytes xargs: argument line too long # 'echo 10' is too long

The following GNU xargs examples:

  • indicate that for each instance of the command, use a sequence of two arguments, if available, or should not be used (without -x ) or should be used (with -x ): -n 2
  • limit each command to no more than 8 (9 - 1) bytes: -s 9

Note. In BSD xargs example below -x works the same, and the -x example should work, but not with the version of xargs found in OSX 10.11.3 and PC-BSD 10.1: whenever -x is specified, the specified <argumentCount> value in -n <argumentCount> ignored and xargs behaves as if -n 1 was specified.

 # NO -x: Use 2 arguments *if possible*. $ echo -e "1 2 3 4a 5 6" | xargs -n 2 -s 9 echo 1 2 3 # 'echo 3 4a' is more than 8 (9 - 1) bytes -> '3' is used *alone* 4a # 'echo 4a 5' also doesn't fit -> '4a' is also used alone. 5 6 # WITH -x: *Must* use 2 arguments (if available); *fail* otherwise. $ echo -e "1 2 3 4a 5 6" | xargs -n 2 -s 9 -x echo xargs: argument list too long # 'echo 3 4a' is too long; cannot use 2 arguments -> error 1 2 

Notice how the error message is sadly printed before the last successful command; this is possibly due to the error mentioned above, so Armali's answer may provide an explanation.

0
source

Source: https://habr.com/ru/post/1312616/


All Articles