2

So, I've been trying for a while and this really won't work. I'm trying to write a script that will concatenate many pdf files into one without the tedium of specifying them at the command-line interface (they all have similar names).

#!/bin/bash 

i=1 
list="science.pdf" 
outputfile="file.pdf" 

while [ $i -le 3 ]; do 
    file="science (${i}).pdf" 
    list="$list $file" 
    let i=i+1 
done 

pdftk $list cat output $outputfile

And this is my output:

sean@taylor:~/Downloads/understanding/s0$ ./unite.sh 
Error: Failed to open PDF file: 
   science
Error: Failed to open PDF file: 
   (1).pdf
Error: Failed to open PDF file: 
   science
Error: Failed to open PDF file: 
   (2).pdf
Error: Failed to open PDF file: 
   science
Error: Failed to open PDF file: 
   (3).pdf
Errors encountered.  No output created.
Done.  Input errors, so no output created.

I figure that somehow the script thinks that the files should be split up wherever therre's a space, but I've tried both a backslash before the space (\ ) and surrounding the file name with a quote (\") to no avail.

Can anyone help please?

2 Answers2

3

Don't append the filenames to a string. Use an array instead:

i=1 
list=( "science.pdf" )
outputfile="file.pdf" 

while [ $i -le 3 ]; do 
    file="science (${i}).pdf" 
    list+=( "$file" )
    let i=i+1 
done 

pdftk "${list[@]}" cat output $outputfile

You can also simplify your script further by using a for-loop as shown below:

list=( "science.pdf" )
for (( i=1; i<=3; i++ )); do
    file="science (${i}).pdf"
    list+=( "$file" )
done
pdftk "${list[@]}" cat output $outputfile
dogbane
  • 266,786
  • 75
  • 396
  • 414
  • wow, I really wasn't expecting such a quick reply... guess I'm really not used to stackoverflow! XD Thanks a lot, I really appreciate it! – Sean Macfoy Apr 09 '13 at 17:21
  • The loop isn't even necessary: `list=(science.pdf science\ {1..3}.pdf)` (in this case; I'm taking advantage of the fixed number of repetitions taken by the loop and the simple structure of the loop body.) – chepner Apr 10 '13 at 12:04
-2

When you execute your final command

pdftk $list cat output $outputfile

The $list variable is no longer quoted, i.e., what is actually being executed is

pdftk science.pdf science (1).pdf ... science (3).pdf cat output file.pdf

You need to super-quote your $list variable. Try:

while [ $i -le 3 ]; do 
    file="science (${i}).pdf" 
    list="$list \"$file\""
    let i=i+1 
done

You may need to use a different method of concatenating variables as your loop will probably continuously unquote the previously concatenated values.

Matt W
  • 476
  • 3
  • 11
  • Adding dogbane's array answer will get you the rest of the way `list+=( "\"$file\"" ); ` – Matt W Apr 09 '13 at 17:22
  • 1
    No. The shell parses quotes *before* replacing variables with their values, so embedding quotes in the variable's (or array's) value won't do anything at all useful. – Gordon Davisson Apr 09 '13 at 22:32