5

i want to compress all my pdf files in an given directory and its sub-directories using ghostscript.

I´m stuck using the find command within loops by filename including spaces.

Here some example code I´m aiming for:

pdffiles=$(find /path/to/directory -type f -name *.pdf)
for file in pdffiles; do
  gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/screen -dNOPAUSE -dBATCH -dQUIET -sOutputFile=new_$file $file; 
  rm $file;
  mv new_$file $file;
done;

Any idea how i could fix the problem with the spaces? Is there a better way to do this?

0
3

Your loop is better written as

find ... | while read -r file

But then you need to make sure you quote the filename inside the loop. So we end up with

find /path/to/directory -type f -name *.pdf | while read -r file
do
  gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/screen -dNOPAUSE -dBATCH -dQUIET -sOutputFile="new_$file" "$file"
  rm "$file"
  mv "new_$file" "$file"
done

(Also note all those ; aren't needed).

Now this loop has potential file ownership/permission issues, but that's another question :-)

3

A single line script is also an option:

find -type f -name "*.pdf" -exec bash -c 'gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/screen -dNOPAUSE -dBATCH -dQUIET -sOutputFile="new.pdf" "{}"; rm "{}"; mv "new.pdf" "{}";' {} \;
2

thank you for your great responses! I refactored my script and it´s running quite good :)

Here is the refactored, improoved code with logging, parameters and some more stuff. I´m always open to improvements about my code. Thanks in advance.

    #!/bin/bash

    ## Script to compress PDF Files using ghostscript incl. subdirs
    ## Copyright (C) 2016 Maximilian Fries - All Rights Reserved
    ## Contact: maxfries@t-online.de
    ## Last revised 2016-07-29

    # Usage
    # ./pdf-compress.sh [screen|ebook|prepress|default] [verbose]

    # Variables and preparation
    {
    count=0
    success=0
    successlog=./success.tmp
    gain=0
    gainlog=./gain.tmp
    pdfs=$(find ./ -type f -name "*.pdf")
    total=$(echo "$pdfs" | wc -l)
    log=./log
    verbose="-dQUIET"
    mode="prepress"
    echo "0" | tee $successlog $gainlog > /dev/null
    }

    # Are there any PDFs?
    if [ "$total" -gt 0 ]; then

    #Parameter Handling & Logging
    {
      echo "-- Debugging for Log START --"
      echo "Number of Parameters: $#"
      echo "Parameters are: $*"
      echo "-- Debugging for Log END   --"
    } >> $log

    # Only compression-mode set
    if [ $# -eq 1 ]; then
      mode="$1"
    fi

    # Also Verbose Level Set
    if [ $# -eq 2 ]; then
      mode="$1"
      verbose=""
    fi

    echo "$pdfs" | while read -r file
    do
      ((count++))
      echo "Processing File #$count of $total Files" | tee -a $log
      echo "Current File: $file "| tee -a $log
      gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS="/$mode" -dNOPAUSE \
      -dBATCH $verbose -sOutputFile="$file-new" "$file" | tee -a $log

      sizeold=$(wc -c "$file" | cut -d' ' -f1)
      sizenew=$(wc -c "$file-new" | cut -d' ' -f1)
      difference=$((sizenew-sizeold))

      # Check if new filesize is smaller
      if [ $difference -lt 0 ]
      then
        rm "$file"
        mv "$file-new" "$file"
        printf "Compression was successfull. New File is %'.f Bytes smaller\n" \
        $((-difference)) | tee -a $log
        ((success++)) 
        echo $success > $successlog
        ((gain-=difference))
        echo $gain > $gainlog
      else
        rm "$file-new"
        echo "Compression was not necessary" | tee -a $log
      fi

    done

    # Print Statistics
    printf "Successfully compressed %'.f of %'.f files\n" $(cat $successlog) $total | tee -a $log
    printf "Safed a total of %'.f Bytes\n" $(cat $gainlog) | tee -a $log

    rm $successlog $gainlog

    else
      echo "No PDF File in Directory"
    fi

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.