Search code examples
bashlsspacespdftk

Filenames with spaces in the middle of a command (not a while/for loop)


I'm trying to provide a list of filenames with spaces to pdftk (to merge 3 PDFs into one PDF) but it doesn't seem to like what I'm trying.

# pdftk INPUT1.pdf INPUT2.pdf output OUTPUTFILE.pdf

It works specifying the files manually:

$ pdftk "pdf 1.pdf" "pdf 2.pdf" output t.pdf
$ ls t.pdf
t.pdf (and it works/opens fine)

But none of the following seem to work:

$ pdftk "$(ls --quoting-style=c | tr "\n" " ")" output t.pdf
Error: Unable to find file.
Error: Failed to open PDF file: 
   "pdf 1.pdf" "pdf 2.pdf" "pdf 3.pdf" 
Errors encountered.  No output created.
Done.  Input errors, so no output created.

(note above, not using quotes around the $(ls) fails too)

or this:

$ ls -1
'pdf 1.pdf'
'pdf 2.pdf'
'pdf 3.pdf'

$ pdftk "$(ls -1 | tr "\n" " ")" output t.pdf
Error: Unable to find file.
Error: Failed to open PDF file: 
   pdf 1.pdf pdf 2.pdf pdf 3.pdf 
Errors encountered.  No output created.
Done.  Input errors, so no output created.

Solution

  • $ pdftk "$(some command)" output t.pdf
    

    This runs some command, then the double quotes encapsulate the output into a single "word". No matter what the command, the result will be that pdftk receives a single argument comprising the entirety of the command's output.

    Parsing ls is generally considered to be a bad idea.

    As suggested by @RavinderSingh13, simply specifying *.pdf (or even *) may resolve your issue. The shell performs "globbing" to expand the wildcards, and correctly splits them into "words" by itself:

    $ pdftk * output t.pdf
    

    If you are running some command other than ls that outputs a list of filenames, you need to be a bit careful that you quote at the correct point.

    Some portable ways to do this (with some assumptions about command output) are given in the "Application Usage" section of the POSIX spec for xargs.

    On systems with GNU versions of utilities (eg. find and xargs) a more robust mechanism is provided using non-standared -print0, -0 and related command parameters that assume the NULL character is the (only) special character used to separate items of command output.