5

Consider the following simple shell script (using pdftk):

#!/bin/sh    
echo "" | ps2pdf -sPAPERSIZE=a4 - blank.pdf

pdftk \
    A=blank.pdf \
    B=blank.pdf \
    C=blank.pdf \
    cat A C \
    output foo.pdf

Now, if I comment out one line, wackiness ensues. Here is the modified script.

#!/bin/sh

echo "" | ps2pdf -sPAPERSIZE=a4 - blank.pdf

pdftk \
    A=blank.pdf \
#   B=blank.pdf \
    C=blank.pdf \
    cat A C \
    output foo.pdf

The output looks like:

Done.  Input errors, so no output created.
cat: A: No such file or directory
cat: C: No such file or directory
cat: output: No such file or directory
%PDF-1.4
%<E2><E3><CF><D3>
4 0 obj 
<<
/Filter /FlateDecode
/Length 23
>>
stream
x<9C>+T0<D0>3T0^@A(<9D><9C><CB>^U<C8>^E^@5I^De
endstream 
endobj 
3 0 obj 
<<
/Resources 
<<
/ProcSet [/PDF]
>>
/Type /Page
/Parent 1 0 R
/Contents 4 0 R
/MediaBox [0 0 595 842]
>>
endobj 
7 0 obj 
<<
/Filter /FlateDecode
/Length 23
>>
stream
x<9C>+T0<D0>3T0^@A(<9D><9C><CB>^U<C8>^E^@5I^De
endstream 
endobj 
6 0 obj 
<<
/Resources 
<<
/ProcSet [/PDF]
>>
/Type /Page
/Parent 1 0 R
/Contents 7 0 R
/MediaBox [0 0 595 842]
>>
endobj 
1 0 obj 
<<
/Kids [3 0 R 6 0 R]
/Type /Pages
/Count 2
>>
endobj 
9 0 obj 
<<
/Type /Catalog
/Pages 1 0 R
>>
endobj 
10 0 obj 
<<
/ModDate (D:20160103144953+05'30')
/CreationDate (D:20160103144953+05'30')
/Creator (pdftk 2.02 - www.pdftk.com)
/Producer (itext-paulo-155 \(itextpdf.sf.net-lowagie.com\))
>>
endobj xref
0 11
0000000000 65535 f 
0000000455 00000 n 
0000000000 65535 f 
0000000112 00000 n 
0000000015 00000 n 
0000000000 65535 f 
0000000332 00000 n 
0000000235 00000 n 
0000000000 65535 f 
0000000520 00000 n 
0000000571 00000 n 
trailer

<<
/Info 10 0 R
/ID [<cd7858cb595d5fbe3dd38c1258972091><390fa471e3236a790d9231e931a73695>]
/Root 9 0 R
/Size 11
>>
startxref
767
%%EOF

Can anyone explain why there is a problem doing this? I assumed that sh (or bash, it doesn't make a difference) would just ignore that line and move on.

Also, is there something similar I can do that would work? When I use pdftk, I pass it a list of files, some of which I may want to comment or uncomment from time to time.

I'm using pdftk 2.02-2 on Debian 8.2 (jessie).


Minimal reproducer for these wondering about the behaviour:

$ cat test.sh
#!/bin/sh
echo \
    A \
#   B \
    C
$ ./test.sh
A
./test.sh: line 5: C: command not found
5
  • What will happen after you run the comment-contained script? I think it should think of C=blank.pdf cat AC output foo.pdf as another command, is it so or am I wrong?
    – Mohammad
    Jan 3, 2016 at 9:58
  • Define "wackiness". Any error messages? Is an output file produced? What actually happens?
    – terdon
    Jan 3, 2016 at 10:40
  • @terdon I added minimal reproducer explaining easier. This was bothering me also once and I didn't find a solution so I am looking forward your insight.
    – Jakuje
    Jan 3, 2016 at 10:49
  • To whoever just made an edit, sorry, it looks like it got bounced. Please feel free to re-add. @terdon Added the output. I just assumed that people could run it themselves, and also that I was making some obvious mistake. Jan 3, 2016 at 11:02
  • @FaheemMitha I don't know what is pdftk, let alone running your script myself. :)
    – Mohammad
    Jan 3, 2016 at 11:24

1 Answer 1

8

The cause

Firstly, let's look at the manual page of bash:

A non-quoted backslash () is the escape character. It preserves the literal value of the next character that follows, with the exception of . If a \<newline> pair appears, and the backslash is not itself quoted, the \<newline> is treated as a line continuation (that is, it is removed from the input stream and effectively ignored).

So when you use \ just before a <newline>, it treats it as a line continuation. But in your second script, the continuation of your code after A=blank.pdf is a comment, and because \ after B=blank.pdf is also a part of your comment, it does not cause line continuation. As a result, the remaining of your script will be treated as another unique command. So bash will think of your script as something like this:

#!/bin/sh

echo "" | ps2pdf -sPAPERSIZE=a4 - blank.pdf

pdftk A=blank.pdf #   B=blank.pdf \
C=blank.pdf cat A C output foo.pdf

Here you will most probably get an error saying something like C=blank.pdf: command not found.

Backticks to the rescue!

However, you can use comments among your line continuations, by using command substitution capability of backticks, like this:

#!/bin/sh

echo "" | ps2pdf -sPAPERSIZE=a4 - blank.pdf

pdftk \
    A=blank.pdf \
`#  B=blank.pdf` `#You added left-side comment and I added this comment and everything is awesome` \
    C=blank.pdf \
    cat A C \
    output foo.pdf

This is not my ingeniuity. It is Marwan Alsabbagh's. See the following link for more detail:

How to Put Line Comment for a Multi-line Command

2
  • I see. Any suggestions about a workaround? Jan 3, 2016 at 10:31
  • good one. You were faster. Just found the same question on SO
    – Jakuje
    Jan 3, 2016 at 10:53

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .