1

I am trying to create a script that lowercases/uppercases files or directories.

 modify [-r] [-l|-u] <dir/file names...>

I am currently using getopts to check for flags. However, I can't run my command like that modify -rl to lowercase recursively my dir / files.

(edit) The code:

#!/bin/bash

FLAGS=""
if [ $# -eq 0 ]
then
    echo -e "No arguments supplied. \nPlease supply an argument.For more information use -h."
else
  while getopts "rluh" opt
  do
    case $opt in
      r)
        FLAGS+=r
        ;;
      l)
        FLAGS+=l
        ;;
      u)
        FLAGS+=u
        ;;
      h)
        FLAGS+=h
        ;;
      *)
        echo "Unrecognized argument. Please enter -h for information"
    esac
  done

fi
if [[ "$FLAGS" == "l" && "$2" -eq 0 ]]
then
  echo "file to modify $2"
elif [[ "$FLAGS" == "h" && "$2" -eq 0 ]] 
then
  echo "Some info"
fi


exit 0
  • Is this a question about how to handle the command line options using getopts or about how to implement lowercasing of filenames? In either case, you have not shown any actual code. – Kusalananda Mar 21 at 16:51
  • Sorry for that. It is actually a question about how to handle options using getopts. – ClemHlrdt Mar 21 at 16:54
2

It's easier if you set individual flags for each option that is activated, so that you don't have yet another string to parse just to check whether an option was used.

For example:

#!/bin/bash

self=$0

show_help () {
    cat <<END_HELP
Usage: $self [-r] [-l|-u] pathname [...]

Options:

    info about options here

END_HELP
}

recurse=0    # don't recurse by default
lowercase=1  # lowercase by default

while getopts rluh opt; do
    case $opt in
        r) recurse=1   ;;
        l) lowercase=1 ;;
        u) lowercase=0 ;;
        h) show_help
           exit ;;
        *) echo 'Error in parsing options' >&2
           exit 1
    esac
done

shift "$(( OPTIND - 1 ))"

for pathname do
    if [ -d "$pathname" ] && [ "$recurse" -eq 1 ]; then
        # recurse here
    fi
    if [ "$lowercase" -eq 1 ]; then
        # turn into lowercase
    else
        # turn into uppercase
    fi
done

Note that the code after the shift is just example code. I would suggest that you instead of a loop considered using find for doing recursion (possibly in all cases, even if the recursion flag isn't set).

The shift, by the way, gets rid of all the parsed options from "$@" so that only pathname operands are left in the list of positional parameters. This is what the loop afterwards iterates over.

The code, as written above uses sensible defaults (these should be mentioned in the help text). This means that it's perfectly ok to run the script without any options. As a side note, running the tool with no arguments whatsoever should probably not result in an error. There's no work to do, so no work should be done.

  • Or use false/true instead of 0/1 and use "$recurse" instead of [ "$recurse" -eq 1 ] – Stéphane Chazelas Mar 21 at 17:38
2

You're concatenating the flag letters to a single string, so with myscript -l -r, you get FLAGS=lr, which isn't equal to either l or r.

You could use pattern matching instead of equality testing to deal with that:

if [[ $FLAGS = *r* ]]; then
    echo "flag -r was given"

or add distinct variables for each flag:

r_flag=
l_flag=
while getopts "rluh" opt; do
    case $opt in
        r) r_flag=1;;
...
if [[ $r_flag ]]; then
    echo "flag -r was given"

In any case, you're very likely to want to shift $(( OPTIND - 1 )) after the while getopts loop, so that the options handled by getopts are removed from the positional parameters, and what's left in $1, $2... are the script arguments given after the options.

0

Something like FLAGS+=r will append r to FLAGS. For modify -r -l FLAGS therefore will be rl. You should use one variable per option (FLAG_r).

The comparision "$2" -eq 0 will only work if the script gets two directory names, with the second one being 0. A better comparision would be "$2" = "".

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.