2
\$\begingroup\$

I'm a student, and most of my lab work includes writing programs (usually .cpp) run them, copy the source code and output to a word file and either mail a pdf to the concerned teacher or submit in print. (I still don't get the point of submitting a program in print or pdf file, but this is what we're asked to do)

So I wrote a little shell script to help me automate this stuff.

The packages I'm using are:

  1. enscript
  2. ps2pdf
  3. pdftk

Here is the script code:

#!/bin/bash

TARGET='/home/angg/code'
cd $TARGET

find . -type f -name '*.cpp' | while read CPPFILE
do
    TITLE=$(basename $CPPFILE .cpp)

    g++ $TITLE.cpp 

    echo $CPPFILE | xargs enscript --color=1 -C -Ecpp -B -t $TITLE -o - | ps2pdf - $TITLE.pdf

    ./a.out > $TITLE.txt && enscript -B $TITLE.txt -o - | ps2pdf - $TITLE.output.pdf

    pdftk $TITLE.pdf $TITLE.output.pdf cat output $TITLE.final.pdf

    rm $TITLE.output.pdf
    rm $TITLE.pdf

done

today=`date +%j-%M`

pdftk *.pdf cat output $today.pdf

I referred this link to convert all cpp files to pdf files, to add output at the end of each cpp file, I created a separate pdf for output of each program and merged the two pdfs together using pdftk and then removing pdfs not needed now

I need a review regarding the code and if I can shorten it. Also, I'm new to all these packages used and would want to know if there's any redundancy I could avoid.

\$\endgroup\$
  • \$\begingroup\$ You're asked to deliver source code in PDF form? That's odd indeed. \$\endgroup\$ – Mast Sep 2 '18 at 16:05
  • \$\begingroup\$ @Mast nope, not pdf, teachers usually want a .doc. I just find .docs ugly, so I prefer pdf. I still don't know how does one read a source code \$\endgroup\$ – nglglhtr Sep 2 '18 at 17:13
  • 1
    \$\begingroup\$ I'm glad to see enscript is still getting used for printing source code. \$\endgroup\$ – chicks Sep 2 '18 at 19:18
2
\$\begingroup\$

Automated suggestions

If you don't have shellcheck installed, grab it, or use the online service. It reports a bunch of questionable constructs:

202986.sh:4:1: warning: Use 'cd ... || exit' or 'cd ... || return' in case cd fails. [SC2164]
202986.sh:6:38: note: read without -r will mangle backslashes. [SC2162]
202986.sh:8:22: note: Double quote to prevent globbing and word splitting. [SC2086]
202986.sh:10:9: note: Double quote to prevent globbing and word splitting. [SC2086]
202986.sh:12:10: note: Double quote to prevent globbing and word splitting. [SC2086]
202986.sh:12:61: note: Double quote to prevent globbing and word splitting. [SC2086]
202986.sh:12:84: note: Double quote to prevent globbing and word splitting. [SC2086]
202986.sh:14:15: note: Double quote to prevent globbing and word splitting. [SC2086]
202986.sh:14:41: note: Double quote to prevent globbing and word splitting. [SC2086]
202986.sh:14:68: note: Double quote to prevent globbing and word splitting. [SC2086]
202986.sh:16:11: note: Double quote to prevent globbing and word splitting. [SC2086]
202986.sh:16:22: note: Double quote to prevent globbing and word splitting. [SC2086]
202986.sh:16:51: note: Double quote to prevent globbing and word splitting. [SC2086]
202986.sh:18:8: note: Double quote to prevent globbing and word splitting. [SC2086]
202986.sh:19:8: note: Double quote to prevent globbing and word splitting. [SC2086]
202986.sh:23:7: note: Use $(..) instead of legacy `..`. [SC2006]
202986.sh:25:7: note: Use ./*glob* or -- *glob* so names with dashes won't become options. [SC2035]
202986.sh:25:24: note: Double quote to prevent globbing and word splitting. [SC2086]

Prefer lower-case for variable names

We normally use upper-case names for environment variables intended to change the behaviour of programs we use. It's better to use lower-case for ordinary shell variables.

Check for program failure

At present, if compilation fails, we'll still proceed, likely with old code. Instead, we should abort execution if any of the steps fail. It's pretty easy to ask the shell to do this for us (though it's worth learning the exceptions); we can also ask it to check we don't expand any undefined variables, too:

set -eu

Useless use of xargs

I've never seen this pattern before:

echo "$filename" | xargs program

Unless your filename contains whitespace (the rest of the code implies it doesn't), that's exactly

program "$filename"

Unusual date conversion

Do you really mean to give the result file a name given by day-within-year and minute-within-hour? That's a surprising combination, and certainly deserves a justifying comment if it is really what you want.

Avoid temporary files

Pipeline processing can produce results with lower latency than storing intermediates to temporary files. We can pipeline one input into pdftk and create the other using a process substitution in roughly this manner:

enscript "$CPPFILE" | ps2pdf \
    | pdftk - <(./a.out | enscript | ps2pdf) \
            cat output "$TITLE.final.pdf"

Consider using Make

If you make a change to a single file, you need to re-run the script (re-doing all the compilation and output processing) to update the final output. Make is more intelligent: you can write pattern rules that enable you to re-build and re-run only what's out of date, without wasting time and energy on the bits that haven't changed.

It can also clean up the temporary files, and you could write a "clean" rule to clean up all the result files.

If you do write a Makefile, be sure to bring it here for review!

\$\endgroup\$
  • \$\begingroup\$ Awesome! Thank you for the detailed review! And yeah, I do need the date conversion, it was so I would have separate folders for the programs done on that particular day. (separate submissions for certain program groups, minute is just for my reference :P) \$\endgroup\$ – nglglhtr Sep 3 '18 at 15:55
  • \$\begingroup\$ It might be problematic if you happen to do two different runs 60 minutes apart (or 120, or 180, etc) - perhaps worth adding a %H in there? \$\endgroup\$ – Toby Speight Sep 3 '18 at 16:13
  • \$\begingroup\$ I admit, I certainly didn't think this through. I had in mind of generating the file at the end of a particular day. But well, you're right. Adding %H won't hurt. Thanks again! :) \$\endgroup\$ – nglglhtr Sep 3 '18 at 17:42
  • \$\begingroup\$ I've been trying to run enscript mergesort.cpp --color=1 -C -Ecpp -B -t merge -o - | ps2pdf | pdftk - <(./a.out | enscript | ps2pdf) cat output out.pdf , it gives me an error on the usage of ps2pdf \$\endgroup\$ – nglglhtr Sep 4 '18 at 7:28
  • \$\begingroup\$ I think the ps2pdf manpage says you need to specify the input filename - give it - to use stdin. (My example was just structure - I omitted most arguments, for brevity.) \$\endgroup\$ – Toby Speight Sep 4 '18 at 7:34

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.