How can I pass all arguments with xargs in middle of command in linux

前端 未结 8 2044
一个人的身影
一个人的身影 2020-12-09 08:37

I want to pass all the files as a single argument on Linux but I am not able to do that.

This is working

ls | sort -n | xargs  -i pdftk  {} cat outpu         


        
相关标签:
8条回答
  • 2020-12-09 08:45

    This is one way to do it

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

    or using backtick

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

    As pointed out in the comments this will not work on filenames containing spaces. In that case you could 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 named " 0 foo " and " 1 bar " then the result of eval would be the desired command, with the file names in double quotes:

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

    If the filenames might contain newlines, then use find command, see discussion by @joeytwiddle in the comments of @andrewdotn's answer. The following solution also handles file names with double quotes using the sed command to escape 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
    
    0 讨论(0)
  • 2020-12-09 08:50

    I know this is not the OP's question, but I found this useful.

    If you want to reshuffle your arguments you can use parallel in combination with xargs.

    # limit the number of arguments per line
    echo last first middle last first middle | xargs -n 3
    last first middle
    last first middle
    

    GNU-parallel can now reshuffle those arguments at will with the --colsep argument.

    echo last first middle last first middle | xargs -n 3 | parallel --colsep=" " echo {2} {3} {1}
    first middle last
    first middle last
    

    You can also add constant arguments in there.

    echo last first middle last first middle | xargs -n 3 | parallel --colsep=" " echo {2} {3} middle2 {1}
    first middle middle2 last
    first middle middle2 last
    
    0 讨论(0)
  • 2020-12-09 08:56

    Here's what I did for the same problem, and am actually using in production:

    cat chapter_order-pdf-sample.txt | xargs -J % pdftk % cat output sample.pdf
    
    0 讨论(0)
  • 2020-12-09 08:58

    You can do this by chaining two calls to xargs. Use the first to chain all of the args together into one string and pass that as a param to echo, and the second using -I to place that chain of args into the place where you want it, as follows:

    ls | sort -n | xargs echo | xargs -I {} pdftk {} cat output combinewd2.pdf
    
    0 讨论(0)
  • 2020-12-09 09:06

    It’s ugly, but you can run sh -c and access the list of arguments passed by xargs as "${@}", like so:

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

    The extra "${0}" at the end is there because, as the sh man page says

    -c string

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

    To test this, let’s first create some files with complicated names that will mess up 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 the arguments are quoted correctly. Note that this will fail if any filenames contain newlines, and that ls -v is basically ls | sort -n.

    0 讨论(0)
  • 2020-12-09 09:06

    This should work on filenames containing spaces, newlines, apostrophes and quotation marks (all of which are possible on UNIX filesystems):

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

    That might be overkill compared to the accepted answer, if you know you are working with simple filenames.

    But if you are writing a script that will be used again in future, it is desirable that it won't explode one day when it meets unusual (but valid) inputs.

    This is basically an adaptation of andrewdotn's answer which terminates input files with a zero-byte, instead of with a newline, hence preserving filenames which contain one or more newline characters.

    The respective options -print0, -z and -0 tell each of the programs that input/output should be delimited by the zero-byte. Three different programs, three different arguments!

    0 讨论(0)
提交回复
热议问题