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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.