1

I have these bash sequence of commands and would like to simplify it. Any help would be appreciated.

  [[ "$fl" == *"img"* ]] && mv "$flimg" "$out"
  [[ "$fl" == *"png"* ]] && mv "$flimg" "$out"
  [[ "$fl" == *"jpg"* ]] && mv "$flimg" "$out"
  [[ "$fl" == *"tif"* ]] && mv "$flimg" "$out"
Vera
  • 1,223

3 Answers3

0

bash supports extended regular expression and you could do all checks in one, like:

[[ $file =~ (img|png|jpg|tif) ]] && echo do-something

to check if the variable file contains any one of those given strings (note that I used =~ operator for the regex matching).

αғsнιη
  • 41,407
0

As an alternative to the regex, a less elegant method would be to combine the conditionals by using OR - which, in Bash, is a double pipe (||):

[[ "$fl" == *"img"* || "$fl" == *"png"* || "$fl" == *"jpg"* || "$fl" == *"tif"* ]] && mv "$flimg" "$out"

Double pipe would also work in Bourne or Korn shell - using just single braces ([]) and changing == to = (for Bourne only), for example

[ "$fl" = *"img"* || "$fl" = *"png"* || "$fl" = *"jpg"* || "$fl" = *"tif"* ] && mv "$flimg" "$out"
Greenonline
  • 1,851
  • 7
  • 17
  • 23
  • What is this kind of construct [[ "$fl" == *"img"* ]] called, with the wildcard thing? – Vera Oct 21 '21 at 03:17
  • 1
    It is called a conditional, [[]] (or []) is equivalent to test. The * is globbing. – Greenonline Oct 21 '21 at 03:45
  • 1
    See also How to compare strings in Bash - there are plenty of useful examples – Greenonline Oct 21 '21 at 04:00
  • [[ ... ]] is absolutely not equivalent to [ ... ] or test. Just try [[ * = * ]] && echo ok and [ * = * ] && echo ok and test * = * && echo ok in a directory with two or more files in it. – Kusalananda Oct 21 '21 at 06:11
  • "Globbing" is when you use a shell pattern to generate a list of filenames. * is a shell pattern. It is a "globbing pattern" when used to generate a list of filenames. In your code, you don't use it as a globbing pattern since you are not doing any globbing. You are doing a pattern match. The == operator is the pattern matching operator in bash. – Kusalananda Oct 21 '21 at 06:14
0

Using POSIX standard sh syntax, which would also be valid in bash, you could use a case statement here:

case $fl in
    *img*|*jpg*|*png*|*tif*)
        mv -- "$flimg" "$out"
esac

or, as a "one-liner",

case $fl in (*img*|*jpg*|*png*|*tif*) mv -- "$flimg" "$out"; esac

If you enable the extglob shell option with shopt -s extglob, you may also use

[[ $fl == *@(img|jpg|png|tif)* ]] && mv -- "$flimg" "$out"

If you only want to test a filename suffix after the last dot in the filename in $fl:

case ${fl##*.} in (img|jpg|png|tif) mv -- "$flimg" "$out"; esac

or, after shopt -s extglob,

[[ ${fl##*.} == @(img|jpg|png|tif) ]] && mv -- "$flimg" "$out"

The standard expansion ${variable##pattern} removes the longest prefix string from $variable that matches pattern. Using *. as the pattern means deleting everything up to and including the last dot in the value.

Note at that all pattern matches done in this answer are by means of shell patterns, not regular expressions.

Kusalananda
  • 333,661