How to pass all arguments using xargs in the middle of a command in linux

I want to transfer all files as a single argument in Linux, but I cannot do this.

It works

ls | sort -n | xargs -i pdftk {} cat output combinewd2.pdf 

This passes one argument per command, but I want everything in one command.

+8
linux xargs
source share
5 answers

This is one way to do it.

 pdftk $(ls | sort -n) cat output combinewd2.pdf 

or using reverse

 pdftk `ls | sort -n` cat output combinewd2.pdf 

As pointed out in the comments, this will not work with filenames containing spaces. In this case, you can use eval

 eval pdftk $(while IFS= read -r file; do echo \"$file\" done < <(ls | sort -n)) cat output combinewd2.pdf 

Suppose there are two files with the name "0 foo" and "1 bar", then the result of the eval will be the desired command with the file names in double quotes:

 pdftk " 0 foo " " 1 bar " cat output combinewd2.pdf 

If the file names may contain newlines, use the find , see @joeytwiddle's discussion in the comments of @andrewdotn's answer. The following solution also processes file names with double quotes, using the sed command to exit double quotes:

 eval pdftk $(while IFS= read -r -d '' file; do echo \"$file\" done < <(find . -maxdepth 1 -type f -print0 | \ sed 's/"/\\"/g'| sort -zn)) cat output combinewd2.pdf 
+13
source share

Its ugly, but you can run sh -c and access the list of arguments passed to xargs as "${@}" , for example:

 ls | sort -n | xargs -d'\n' sh -c 'pdftk "${@}" cat output combinewd2.pdf' "${0}" 

There is an extra "${0}" at the end, because, as sh says,

-c string

If the -c option is present, then the commands are read from the line. If there are arguments after the line, they are assigned to positional parameters starting at $ 0 .

To verify this, first create some files with complex names that will ruin most other solutions:

 $ seq 1 100 | xargs -I{} touch '{} with "spaces"' $ ls 1 with "spaces" 31 with "spaces" 54 with "spaces" 77 with "spaces" 10 with "spaces" 32 with "spaces" 55 with "spaces" 78 with "spaces" 100 with "spaces" 33 with "spaces" 56 with "spaces" 79 with "spaces" 11 with "spaces" 34 with "spaces" 57 with "spaces" 8 with "spaces" 12 with "spaces" 35 with "spaces" 58 with "spaces" 80 with "spaces" 13 with "spaces" 36 with "spaces" 59 with "spaces" 81 with "spaces" 14 with "spaces" 37 with "spaces" 6 with "spaces" 82 with "spaces" 15 with "spaces" 38 with "spaces" 60 with "spaces" 83 with "spaces" 16 with "spaces" 39 with "spaces" 61 with "spaces" 84 with "spaces" 17 with "spaces" 4 with "spaces" 62 with "spaces" 85 with "spaces" 18 with "spaces" 40 with "spaces" 63 with "spaces" 86 with "spaces" 19 with "spaces" 41 with "spaces" 64 with "spaces" 87 with "spaces" 2 with "spaces" 42 with "spaces" 65 with "spaces" 88 with "spaces" 20 with "spaces" 43 with "spaces" 66 with "spaces" 89 with "spaces" 21 with "spaces" 44 with "spaces" 67 with "spaces" 9 with "spaces" 22 with "spaces" 45 with "spaces" 68 with "spaces" 90 with "spaces" 23 with "spaces" 46 with "spaces" 69 with "spaces" 91 with "spaces" 24 with "spaces" 47 with "spaces" 7 with "spaces" 92 with "spaces" 25 with "spaces" 48 with "spaces" 70 with "spaces" 93 with "spaces" 26 with "spaces" 49 with "spaces" 71 with "spaces" 94 with "spaces" 27 with "spaces" 5 with "spaces" 72 with "spaces" 95 with "spaces" 28 with "spaces" 50 with "spaces" 73 with "spaces" 96 with "spaces" 29 with "spaces" 51 with "spaces" 74 with "spaces" 97 with "spaces" 3 with "spaces" 52 with "spaces" 75 with "spaces" 98 with "spaces" 30 with "spaces" 53 with "spaces" 76 with "spaces" 99 with "spaces" $ ls | sort -n | xargs -d'\n' sh -c 'set -x; pdftk "${@}" cat output combinewd2.pdf' "${0}" + pdftk '1 with "spaces"' '2 with "spaces"' '3 with "spaces"' '4 with "spaces"' '5 with "spaces"' '6 with "spaces"' '7 with "spaces"' '8 with "spaces"' '9 with "spaces"' '10 with "spaces"' '11 with "spaces"' '12 with "spaces"' '13 with "spaces"' '14 with "spaces"' '15 with "spaces"' '16 with "spaces"' '17 with "spaces"' '18 with "spaces"' '19 with "spaces"' '20 with "spaces"' '21 with "spaces"' '22 with "spaces"' '23 with "spaces"' '24 with "spaces"' '25 with "spaces"' '26 with "spaces"' '27 with "spaces"' '28 with "spaces"' '29 with "spaces"' '30 with "spaces"' '31 with "spaces"' '32 with "spaces"' '33 with "spaces"' '34 with "spaces"' '35 with "spaces"' '36 with "spaces"' '37 with "spaces"' '38 with "spaces"' '39 with "spaces"' '40 with "spaces"' '41 with "spaces"' '42 with "spaces"' '43 with "spaces"' '44 with "spaces"' '45 with "spaces"' '46 with "spaces"' '47 with "spaces"' '48 with "spaces"' '49 with "spaces"' '50 with "spaces"' '51 with "spaces"' '52 with "spaces"' '53 with "spaces"' '54 with "spaces"' '55 with "spaces"' '56 with "spaces"' '57 with "spaces"' '58 with "spaces"' '59 with "spaces"' '60 with "spaces"' '61 with "spaces"' '62 with "spaces"' '63 with "spaces"' '64 with "spaces"' '65 with "spaces"' '66 with "spaces"' '67 with "spaces"' '68 with "spaces"' '69 with "spaces"' '70 with "spaces"' '71 with "spaces"' '72 with "spaces"' '73 with "spaces"' '74 with "spaces"' '75 with "spaces"' '76 with "spaces"' '77 with "spaces"' '78 with "spaces"' '79 with "spaces"' '80 with "spaces"' '81 with "spaces"' '82 with "spaces"' '83 with "spaces"' '84 with "spaces"' '85 with "spaces"' '86 with "spaces"' '87 with "spaces"' '88 with "spaces"' '89 with "spaces"' '90 with "spaces"' '91 with "spaces"' '92 with "spaces"' '93 with "spaces"' '94 with "spaces"' '95 with "spaces"' '96 with "spaces"' '97 with "spaces"' '98 with "spaces"' '99 with "spaces"' '100 with "spaces"' cat output combinewd2.pdf 

All arguments are correctly quoted. Note that this will happen if the file names contain newlines and that ls -v is basically ls | sort -n ls | sort -n .

+9
source share

Use the -I option:

 echo prefix | xargs -I % echo % post 

Output:

 prefix post 
+8
source share

This should work with file names containing spaces, newlines, apostrophes, and quotation marks (all this is possible on UNIX file systems):

 find . -maxdepth 1 -type f -print0 | sort -zn | xargs -0 sh -c 'pdftk "$@" cat output combinewd2.pdf' "$0" 

This may be redundant compared to the accepted answer if you know that you are working with simple file names.

But if you are writing a script that will be used again in the future, it is advisable that it does not explode one day when it encounters unusual (but valid) inputs.

This is basically an adaptation of the andrewdotn response, which interrupts input files with a zero byte rather than a newline, hence preserving the names of files that contain one or more newline characters.

The corresponding options -print0 , -z and -0 tell each program that I / O should be separated by a zero byte. Three different programs, three different arguments!

+2
source share

The problem is that xargs can put individual arguments in the middle of the command with -i and {} , it refuses to do this for several arguments. This, apparently, is supervision, which ultimately causes us a lot of problems!

Besides the above solutions, another alternative is to simply add the arguments you want to find after the files to the end of the file list.

 ( ls | sort -n echo cat echo output echo combinewd2.pdf ) | xargs -d'\n' pdftk 

This approach does not work with file names containing newlines . In this rare case, you should pass strings terminated with a null byte to xargs, as suggested in my other answer.

0
source share

All Articles