0

I have this code below:

#!/bin/bash

filename=$1
file_extension=$( echo $1 | cut -d. -f2 )
directory=${filename%.*}

if [[ -z $filename ]]; then
    echo "You forgot to include the file name, like this:"
    echo "./convert-pdf.sh my_document.pdf"
else
    if [[ $file_extension = 'pdf' ]]; then
        [[ ! -d $directory ]] && mkdir $directory
        convert $filename -density 300 $directory/page_%04d.jpg
    else
        echo "ERROR! You must use ONLY PDF files!"
    fi
fi

And it is working perfectly well!

I would like to create a script which I can do something like this: ./script.sh *.pdf

How can I do it? Using asterisk.

Thank you for your time!

Zissouu
  • 924
  • 2
  • 10
  • 17

2 Answers2

2

Firstly realize that the shell will expand *.pdf to a list of arguments. This means that your shell script will never ever see the *. Instead it will get a list of arguments.

You can use a construction like the following:

#!/bin/bash

function convert() {
  local filename=$1
  # do your thing here
}

if (( $# < 1 )); then
  # give your error message about missing arguments
fi
while (( $# > 0 )); do
  convert "$1"
  shift
done

What this does is first wrap your functionality in a function called convert. Then for the main code it first checks the number of arguments passed to the script, if this is less than 1 (i.e. none) you give the error that a filename should be passed. Then you go into a while loop which is executed as long as there are arguments remaining. The first argument you pass to the convert function which does what your script already does. Then the shift operation is performed, what this does is it throws away the first argument and then shifts all the remaining arguments "left" by one place, that is what was $2 now is $1, what was $3 now is $2, etc. By doing this in the while loop until the argument list is empty you go through all the arguments.

By the way, your initial assignments have a few issues:

  • you can't assume that the filename has an extension, your code could match a dot in some directory path instead.
  • your directory assignment seems to be splitting on . instead of /
  • your directory assignment will contain the filename if no absolute or relative path was given, i.e. only a bare filename
  • ...

I think you should spend a bit more time on robustness

wich
  • 16,709
  • 6
  • 47
  • 72
  • `convert "$1"`, not `convert($1)`. And avoid the `function` keyword -- it makes code incompatible with POSIX-baseline shells for no good reason (unlike bashisms, like `(( ))`, that actually add value). – Charles Duffy Sep 26 '17 at 15:14
  • @CharlesDuffy thanks, using too many languages at once it seems... corrected the function call. I don't really agree about the function keyword, it makes it much clearer to people no so familiar with shell script that a function is being defined and since it is an actual bash script anyway the incompatibility is a moot point. I should make clear that it is a bash script however, I'll add the appropriate hashbang. – wich Sep 26 '17 at 15:17
  • btw, the point of using `:` instead of `#` for placeholders is that it leaves your code syntactically valid even if nobody fills in the placeholder. With just the comment in the body of a conditional or loop it won't parse. – Charles Duffy Sep 26 '17 at 15:18
  • Re: the `function` keyword, choosing to use it in examples makes the portable syntax being less-frequently recognized amongst newcomers a self-fulfilling prophecy. – Charles Duffy Sep 26 '17 at 15:19
0

Wrap your code in a loop. That is, instead of:

filename=$1
: code goes here

use:

for filename in "$@"; do
  : put your code here
done
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441