Book-binging script
Linux,  Programming

Bash for Book-binding

Book-binding using bash

3 Years ago I decided I wanted to make a big change in my live. I wanted to do what I always seamed to do best, work with computers, more specifically, I wanted to learn more about Linux and programming. There was only one problem, I hate reading long texts on a screen, leave alone entire books… So first thing I did was write me some scripts to transform pdf files that way it could be printed to bind it later as a real book the book-binding way .

In this post I will evaluate my script for people who are interested in it to do similar things in Bash. The script is only tested in native Linux, not in the bash included in Windows.

Making the preparations

workingdir=$(pwd)
tmpdir=pdf2bind-$RANDOM
sourcefile=$1
outfile="$workingdir/binding.pdf"

// Make the temporary directory and cd into it
mkdir ~/$tmpdir
cd ~/$tmpdir

First off we have to tell some important things to the script. On line 1 we pass the current directory (where we run the script, not where te script is located) the workingdir variable.
We also need a temporary directory to store some files, to make sure we have a empty directory to work in, we give it a random part in its name.
To know the source file to work with we read the first argument given with the command. The file to save to will be customizable in the final version of the script, but for now, to keep it simple, we will work with binding.pdf. In the final version we will also look if the output file already exists.

Making the bundles

// Create a postscript version of the source file
pdftops $workingdir/$sourcefile ps.ps

// Bundle the pages of the postscript file
declare -i bundlenr=1
for (( i=1; i < `pdfinfo $workingdir/$sourcefile | grep Pages | sed 's/[^0-9]*//'`; i=$i+32 )); do
    psselect -q -p`declare -i j=$i
                while (($j < $i+31)) do j=$j+1 done if (( `gs -o /dev/null -sDEVICE=bbox out${bundlenr}.ps 2>&1 | grep HiResBoundingBox | wc -l` < 6 )) then psjoin out$(( $bundlenr-1 )).ps out${bundlenr}.ps > out$(( $bundlenr-1  ))
        mv out$(( $bundlenr-1 )) out$(( $bundlenr-1 )).ps 
        rm out$(( $bundlenr )).ps
    fi
    bundlenr=$bundlenr+1
done

// Remove the temporary postscript source file
rm ps.ps

add_leading_zero "out" ".ps"

bundlenr=1
for file in ./out*.ps
do
    psbook $file | psnup  -b1.4cm -s0.6 -pa4 -2 > book_$bundlenr.ps
    ps2pdf book_$bundlenr.ps book_$bundlenr.pdf
    bundlenr=$bundlenr+1
done

The first thing we still have to do before we can start editing the file is to make a postscript version of it. The reason is pdf is a proprietary format owned by Adobe and so there are not that many good editing applications laying around for it as there are for postscript.
Once we have or ps file the magic can begin, from line 6 to 23 a loop will iterate over the file to make little bundles of it that are small enough to sew them together later on, if your book leaves your printer! I will not go over the details of this for-loop, if you are interested in this part you should take some time to figure it out four yourselves.

Afterwards we can dismiss of the postscript source file, and, very important, we should add some leading zeros to the bundle file to make it easier ordering them. The function to do this will be given later on. from now on we are going to work with pdf again, so we make a pdf version of all the bundles.

The finishing touch

add_leading_zero "book_" ".pdf"
pdfunite `echo ./book_*.pdf` book.pdf
mv book.pdf $outfile
cd $workingdir
rm -rf ~/$tmpdir

The bundles now are ready, but it would be nice to have it all back in one file, so that’s exactly what the last part of the script is for. After reuniting the bundles into the output file, the temporary files can be safely removed.

bash does not know add_leading_zero!!

function add_leading_zero {
prefix=$1
suffix=$2
baseprefix=$(basename $prefix | sed -e 's/[]\/()$*.^|[]/\\&/g')
dirprefix=$(dirname $prefix)
for filename in "$prefix"*"$suffix"
do
    base=$(basename "$filename")
    index=$(echo "$base" | sed -rn "s/$baseprefix([0-9]+)$suffix$/\1/p")
    newbase=$(printf "$baseprefix%04d$suffix" $index)
    mv $filename "$dirprefix/$newbase"
done
}

We still have to make the function to add the leading zero where necessary, that is what this script will do. As you can see it takes exactly two arguments, the part of the filename before and after the number in the filename.

The full script

On github you can find the full working version. You can see it has some extra options that I added to it in time.

If you think it is still missing something or you know a better way to do some parts of it, please feel free to contribute to it on github

If you like some more information about book-binding, you can take a look here

3 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *