4

I'm quite new to Bash so this might be something trivial, but I'm just not getting it. I'm trying to escape the spaces inside filenames. Have a look. Note that this is a 'working example' - I get that interleaving files with blank pages might be accomplished easier, but I'm here about the space.

#! /bin/sh

first=true
i=combined.pdf
o=combined2.pdf
for f in test/*.pdf
do
    if $first; then
        first=false
        ifile=\"$f\"
    else
        ifile=$i\ \"$f\"
    fi
    pdftk $ifile blank.pdf cat output $o
    t=$i
    i=$o
    o=$t
    break
done

Say I have a file called my file.pdf (with a space). I want the ifile variable to contain the string combined.pdf "my file.pdf", such that pdftk is able to use it as two file arguments - the first one being combined.pdf, and the second being my file.pdf.

I've tried various ways of escaping (with or without first escaping the quotes themselves, etc.), but it keeps splitting my and file.pdf when executing pdftk.

EDIT: To clarify: I'm trying to pass multiple file names (as multiple arguments) in one variable to the pdftk command. I would like it to recognise the difference between two file names, but not tear one file name apart at the spaces.

Joost
  • 4,094
  • 3
  • 27
  • 58
  • 1
    Not to being annoying but two seconds of googling and I found this: http://www.lornajane.net/posts/2011/combining-pdf-files-with-pdftk – Adam Gent Oct 01 '13 at 18:06
  • This is a 'minimal working example' of my issue, though. I'm doing a few other things before appending the files. – Joost Oct 01 '13 at 18:11
  • Ah because you you need a blank page between each page. I did not see that. – Adam Gent Oct 01 '13 at 18:13
  • Why are you getting so complicated? Use 2 variables: `pdftk "$i" "$f" ...` – glenn jackman Oct 01 '13 at 18:30
  • @AdamGent - thanks for the pointer to lornajane.net/posts/2011/combining-pdf-files-with-pdftk - I learnt something new with the -J option to xargs – jaygooby Nov 13 '14 at 11:31

2 Answers2

8

Putting multiple arguments into a single variable doesn't make sense. Instead, put them into an array:

args=(combined.pdf "my file.pdf");

Notice that "my file.pdf" is quoted to preserve whitespace.

You can use the array like this:

pdftk "${args[@]}" ...

This will pass two separate arguments to pdftk. The quotes in "${args[@]}" are required because they tell the shell to treat each array element as a separate "word" (i.e. do not split array elements, even if they contain whitespace).

As a side note, if you use bashisms like arrays, change your shebang to

#!/bin/bash
ThisSuitIsBlackNot
  • 23,492
  • 9
  • 63
  • 110
  • I'm pretty sure that will not work correctly if the file has spaces in it. I remember having issues doing something like that once. – Adam Gent Oct 01 '13 at 18:03
  • This is what I should've started doing right from the start. It's nonsense to try to use a string for this. Thanks! – Joost Oct 01 '13 at 18:06
  • 1
    @AdamGent From the `bash` manpage section on arrays: `If the word is double-quoted,...${name[@]} expands each element of name to a separate word.` In other words, array elements are *not* split on whitespace. – ThisSuitIsBlackNot Oct 01 '13 at 18:08
  • @ThisSuitIsBlackNot I don't recall the exact issue but I believe it was an issue with a new line character in the file name. I had to use a null separator ala find/xargs combo. – Adam Gent Oct 01 '13 at 18:14
  • 2
    The problem of `xargs` parsing the output from `find` is a different problem from quoting whitespace to prevent the shell from performing word-splitting on it. – chepner Oct 01 '13 at 18:16
1

Try:

find test/*.pdf | xargs -I % pdftk % cat output all.pdf

As I said in my comments on other answers xargs is the most efficient way to do this.

EDIT: I did not see you needed a blank page but I suppose you could pipe the find above to some command to put the blank page between (similar to a list->string join). I prefer this way as its more FP like.

Adam Gent
  • 47,843
  • 23
  • 153
  • 203
  • You're not escaping the spaces. This should be `find test/*.pdf -print0 | xargs -0 -J % pdftk % cat output all.pdf` – jaygooby May 28 '15 at 08:59