2

I have a script that organizes files in my downloads directory according to their filetype.

function moveto {
    for filename in *
    do
    case "${filename##*.}" in
        $1 ) echo "!";; # echo statement for debugging
    esac
    done
}

I have a .png file in my downloads directory and nothing else.
When I call moveto "png", the exclamation mark appears.
When I call moveto "png|jpg", the exclamation mark doesn't appear.
When I simply type png|jpg into the case statement, using no variables, the exclamation mark appears.

I've tried changing things up more than a few ways; using single quotes, double quotes, no quotes, aliases, etc., nothing seems to work. Would be great if someone could help out.

smci
  • 32,567
  • 20
  • 113
  • 146
Zacatexas
  • 123
  • 4

1 Answers1

5

The | in a case statement is part of the syntax of the case statement, so it must be part of the source code. (The same is true of the ) terminating the pattern list.)

You can get the effect you want by enabling extended globs (shopt -s extglob) and then using one:

moveto "@(png|jpg)"

Extended glob patterns are documented in the bash manual; they consist of one of the characters *, +, ?, @, or ! followed by a parenthesized list of patterns separated by |. The initial character meanings are mostly familiar:

* zero or more repetitions of any of the patterns
+ one or more repetitions of any of the patterns
? nothing or exactly one of the patterns
@ exactly one of the patterns
! does not match any of the patterns

If you wanted to get fancy, you could assemble the pattern yourself:

moveto() {
  local pattern="@($(tr ' ' '|'<<<"$*"))"
  local filename
  for filename in *; do
    case "${filename##*.}" in
      $pattern) echo "!";; # echo statement for debugging
    esac
  done
}

moveto png jpg
rici
  • 234,347
  • 28
  • 237
  • 341