3
\$\begingroup\$

I developed this script in dead time to be able to compress the PDFs that they send me to university and also to be able to send scans to the various institutions that require formats that do not weigh more than 2Mb.

github link: https://github.com/NF02/pdfcomp

#!/bin/sh
#- Function -#
command_exists() {
  command -v "$@" >/dev/null 2>&1
}

pdfcomprimer(){
    gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=$comp -dNOPAUSE \
        -dQUIET -dBATCH -sOutputFile=$pdfOut $pdfIn
}
pdfcomprimerPrev() {
    echo $pdfIn
    if [[ $pdfIn == "" ]]; then
    echo "Missing input files, try again!"
    exit -1
    fi
    while [ "$con" != "quit" ]
      do
        cat << 'EOF'
 ___________ _____________________________________________________________
|  Quality  | Description                                                 |
|-----------|-------------------------------------------------------------|
| screen    | The output file will have up to 72 DPI.                     |
| ebook     | The output file will have up to 150 DPI.                    |
| preprint  | The output file will have up to 300 DPI.                    |
| printer   | The output files will have up to 300 DPI and will be ready  |
|           | for printing                                                |
| default   | It depends on which of the above options is assigned as the |
|           | “default”.                                                  |
| quit      | Close the program                                           |
|           |                                                             |
 -------------------------------------------------------------------------
EOF
        echo "Select the degree of compression: "
        read con
        if [[ $con == "quit" ]]; then
            exit 0
        fi
    
        if [[ $con == "" ]];then
           con="default"
        fi
           
            gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=$comp -dNOPAUSE \
           -dQUIET -dBATCH -sOutputFile=/tmp/prev.pdf $pdfIn
    if [[ $con == "screen" ]] || [[ $con == "ebook" ]] || [[ $con == "preprint" ]] || [[ $con == "print" ]] || [[ $con == "default" ]]; then
        echo "
 ____________________ _____________________________________ ___________________
|  Source file       |          output file                | Compression level |
 ------------------------------------------------------------------------------
  $(du -sh $pdfIn)        $(du -sh /tmp/prev.pdf)                 $con           
 ==============================================================================
    "   
        else echo "format not found"
    fi

    
    done
    exit 0
}

if ! command_exists gs; then
    echo "ghostscript is not installed"
    exit -1
fi

#-  -#
comp="/default"
pdfIn=$1
pdfOut=$2

if [[ $1 == "-fl" ]] || [[ $1 == "--format-list" ]];then
    cat << 'EOF'
 ___________ _____________________________________________________________
|  Quality  | Description                                                 |
|-----------|-------------------------------------------------------------|
| screen    | The output file will have up to 72 DPI.                     |
| ebook     | The output file will have up to 150 DPI.                    |
| preprint  | The output file will have up to 300 DPI.                    |
| printer   | The output files will have up to 300 DPI and will be ready  |
|           | for printing                                                |
| default   | It depends on which of the above options is assigned as the |
|           | “default”.                                                  |
|           |                                                             |
 -------------------------------------------------------------------------
EOF
    exit 0
fi

if [[ $1 == --help ]] || [[ $1 == -h ]] || [[ $1 == -HELP ]] || [[ $1 == "" ]]; then
    cat << 'EOF'
┏━┓╺┳┓┏━╸┏━╸┏━┓┏┳┓┏━┓   ┏━┓ ╺┓
┣━┛ ┃┃┣╸ ┃  ┃ ┃┃┃┃┣━┛   ┃┃┃  ┃
╹  ╺┻┛╹  ┗━╸┗━┛╹ ╹╹     ┗━┛╹╺┻╸
This application allows you to compress PDFs, using ghostscript, this script
is designed to simplify and speed up the use of the tool, making it more 
user-friendly and practical.
----------------------------------------------------------------------------
-                               commands                                   -
----------------------------------------------------------------------------
-h  (--help): shows help on screen, with all passable parameters.
-f  (--format): allows you to select the compression level
-fl (--format-list): shows the list of possible compression levels.
EOF
    exit 0
fi

if [[ $1 == "-f" ]] || [[ $1 == "--format" ]];then
    pdfIn=$3
    pdfOut=$4
    if [[ $2 == "screen" ]] || [[ $2 == "ebook" ]] || [[ $2 == "preprint" ]] ||
        [[ $2 == "print" ]] || [[ $con == "default" ]]; then
        comp="/$2"
        else echo "format not exists" && exit -4
    fi
fi
if [[ $1 == "-p" ]] || [[ $1 == "--prev" ]]; then
    pdfIn=$2
    pdfcomprimerPrev
fi
   
if [[ $pdfIn == "" ]] || [[ $pdfOut == "" ]]; then
    echo "Missing input/output files, try again!"
    else if  [[ $pdfIn == $pdfOut ]];then
        echo "You can't overwrite this file"
        else if test -f "$pdfIn"; then
                pdfcomprimer
            else echo "Input file not exists"
        fi
    fi
fi
\$\endgroup\$
3
  • 1
    \$\begingroup\$ Note that comprimer is not a word of the English language. At first glance I read it as coprimer and wondered what mathematics has to do with it. Maybe you want to rename it to compressor, so that one can easily grasp what it's about. Of course you can also insist on your poetic freedom. ;) \$\endgroup\$ Oct 3, 2022 at 20:45
  • 1
    \$\begingroup\$ I get the feeling that "comprimer" is a French calque. \$\endgroup\$ Oct 4, 2022 at 9:11
  • \$\begingroup\$ I have taken the poetic license to be able to use a different term than usual, even if I don't think it's a problem, since the documentation is in English and one will also arrive in Italian \$\endgroup\$
    – NFVblog
    Oct 6, 2022 at 9:16

1 Answer 1

2
\$\begingroup\$

Here are a few advices.

Indentation

The "if/else/fi" block such as:

    if [[ $2 == "screen" ]] || [[ $2 == "ebook" ]] || [[ $2 == "preprint" ]] ||
        [[ $2 == "print" ]] || [[ $con == "default" ]]; then
        comp="/$2"
        else echo "format not exists" && exit -4
    fi

would probably be easier to read if is was written as:

    if [[ $2 == "screen" ]] || [[ $2 == "ebook" ]] || [[ $2 == "preprint" ]] ||
        [[ $2 == "print" ]] || [[ $con == "default" ]]; then
        comp="/$2"
    else
        echo "format not exists" && exit -4
    fi

This is even more relevant for the last part of the code:

if [[ $pdfIn == "" ]] || [[ $pdfOut == "" ]]; then
    echo "Missing input/output files, try again!"
    else if  [[ $pdfIn == $pdfOut ]];then
        echo "You can't overwrite this file"
        else if test -f "$pdfIn"; then
                pdfcomprimer
            else echo "Input file not exists"
        fi
    fi
fi

which should/could be rewritten as:

if [[ $pdfIn == "" ]] || [[ $pdfOut == "" ]]; then
    echo "Missing input/output files, try again!"
else
    if  [[ $pdfIn == $pdfOut ]];then
        echo "You can't overwrite this file"
    else
        if test -f "$pdfIn"; then
            pdfcomprimer
        else
            echo "Input file not exists"
        fi
    fi
fi

or even better, using the elif keyword:

if [[ $pdfIn == "" ]] || [[ $pdfOut == "" ]]; then
    echo "Missing input/output files, try again!"
elif  [[ $pdfIn == $pdfOut ]];then
    echo "You can't overwrite this file"
elif test -f "$pdfIn"; then
    pdfcomprimer
else
    echo "Input file not exists"
fi

Consistency

Various stylistic parts of the code are inconsistent:

  • indentation is 2 or 4 spaces
  • there is 0 or 1 whitespace before brackets ("{")

Write/reuse functions

You've defined small functions such as command_exists ans this is a great idea.

I think you can define even more functions, in particular to deal with output to the user. These huge wall of texts make the actual logic in the code harder. Also, one of the literal string is duplicated making things harder to maintain.

Here is a suggestion:

show_format_resolution() {
    cat << 'EOF'
 ___________ _____________________________________________________________
|  Quality  | Description                                                 |
|-----------|-------------------------------------------------------------|
| screen    | The output file will have up to 72 DPI.                     |
| ebook     | The output file will have up to 150 DPI.                    |
| preprint  | The output file will have up to 300 DPI.                    |
| printer   | The output files will have up to 300 DPI and will be ready  |
|           | for printing                                                |
| default   | It depends on which of the above options is assigned as the |
|           | “default”.                                                  |
| quit      | Close the program                                           |
|           |                                                             |
 -------------------------------------------------------------------------
EOF
}

show_help() {
    cat << 'EOF'
┏━┓╺┳┓┏━╸┏━╸┏━┓┏┳┓┏━┓   ┏━┓ ╺┓
┣━┛ ┃┃┣╸ ┃  ┃ ┃┃┃┃┣━┛   ┃┃┃  ┃
╹  ╺┻┛╹  ┗━╸┗━┛╹ ╹╹     ┗━┛╹╺┻╸
This application allows you to compress PDFs, using ghostscript, this script
is designed to simplify and speed up the use of the tool, making it more 
user-friendly and practical.
----------------------------------------------------------------------------
-                               commands                                   -
----------------------------------------------------------------------------
-h  (--help): shows help on screen, with all passable parameters.
-f  (--format): allows you to select the compression level
-fl (--format-list): shows the list of possible compression levels.
EOF
}

Another function which could be useful would be a function checking whether a format is valid.

Indeed, you have:

    if [[ $con == "screen" ]] || [[ $con == "ebook" ]] || [[ $con == "preprint" ]] || [[ $con == "print" ]] || [[ $con == "default" ]]; then

and then:

    if [[ $2 == "screen" ]] || [[ $2 == "ebook" ]] || [[ $2 == "preprint" ]] ||
        [[ $2 == "print" ]] || [[ $con == "default" ]]; then

and I suspect the second last check of the latter is actually wrong.

Checking the error code of echo

I'm not sure to get the point of doing echo "format not exists" && exit -4. In the case where echo would fail, your script would not exit which is probably not the desired behavior. You could write: echo "format not exists"; exit -4.

Argument management

The way pdfIn and pdfOut get assigned $1 and $2 only to be reassigned in almost all useful cases makes things pretty confusing.

Also, it may be worth providing the values explicitly to pdfcomprimerPrev and pdfcomprimer instead of relying on global variables.

Switch case

Various parts of the logic relying on if and various checks could be written in a more concise way using the case/esac statement.

\$\endgroup\$
5
  • \$\begingroup\$ true you are right, however that function for checking the existence of the controls was a convenient solution to avoid problems \$\endgroup\$
    – NFVblog
    Oct 5, 2022 at 22:22
  • \$\begingroup\$ I'm not sure to understand which part of my comment you are replying to... \$\endgroup\$
    – SylvainD
    Oct 6, 2022 at 8:37
  • \$\begingroup\$ both to the part related to the error correction and to that of the existence control function \$\endgroup\$
    – NFVblog
    Oct 6, 2022 at 9:12
  • 1
    \$\begingroup\$ I don't understand your comments either. SylvainD said it's good you used functions, and using more functions would be even better. If you disagree, please clarify. If you don't disagree then great, we already agree. \$\endgroup\$
    – janos
    Oct 6, 2022 at 11:16
  • \$\begingroup\$ the script already works quite well, I just wanted to see if some parts could be written better, nothing more, however it is functional and has a good interface according to what other users have told me. but as always I prefer to have comparisons to improve it and since no one has come to open specific threads I thought I'd start. I have been programming for several years and I have always had the obsession of comparison, sometimes I accepted changes sometimes not, obviously if there are problems, for example a too repetitive syntax I try to correct it if there are cleaner ways to do it \$\endgroup\$
    – NFVblog
    Oct 6, 2022 at 13:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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