Mike
Mike

Reputation: 19737

Regular Expressions for file name matching

In Bash, how does one match a regular expression with multiple criteria against a file name? For example, I'd like to match against all the files with .txt or .log endings.

I know how to match one type of criteria:

for file in *.log
do
        echo "${file}"
done

What's the syntax for a logical or to match two or more types of criteria?

Upvotes: 17

Views: 53485

Answers (6)

Dennis Williamson
Dennis Williamson

Reputation: 360703

You can also do this:

shopt -s extglob
for file in *.+(log|txt)

which could be easily extended to more alternatives:

for file in *.+(log|txt|mp3|gif|foo)

Upvotes: 4

thkala
thkala

Reputation: 86443

Bash does not support regular expressions per se when globbing (filename matching). Its globbing syntax, however, can be quite versatile. For example:

for i in A*B.{log,txt,r[a-z][0-9],c*} Z[0-5].c; do
...
done

will apply the loop contents on all files that start with A and end in a B, then a dot and any of the following extensions:

  • log
  • txt
  • r followed by a lowercase letter followed by a single digit
  • c followed by pretty much anything

It will also apply the loop commands to an file starting with Z, followed by a digit in the 0-5 range and then by the .c extension.

If you really want/need to, you can enable extended globbing with the shopt builtin:

shopt -s extglob

which then allows significantly more features while matching filenames, such as sub-patterns etc.

See the Bash manual for more information on supported expressions:

http://www.gnu.org/software/bash/manual/bash.html#Pattern-Matching

EDIT:

If an expression does not match a filename, bash by default will substitute the expression itself (e.g. it will echo *.txt) rather than an empty string. You can change this behaviour by setting the nullglob shell option:

shopt -s nullglob

This will replace a *.txt that has no matching files with an empty string.

EDIT 2:

I suggest that you also check out the shopt builtin and its options, since quite a few of them affect filename pattern matching, as well as other aspects of the the shell:

http://www.gnu.org/software/bash/manual/bash.html#The-Shopt-Builtin

Upvotes: 24

Error 454
Error 454

Reputation: 7315

You simply add the other conditions to the end:

for VARIABLE in 1 2 3 4 5 .. N
do
    command1
    command2
    commandN
done

So in your case:

for file in *.log *.txt
do
        echo "${file}"
done

Upvotes: 4

ajreal
ajreal

Reputation: 47331

for file in *.{log,txt} ..

Upvotes: 9

mpapis
mpapis

Reputation: 53188

for f in $(find . -regex ".*\.log")
do 
  echo $f
end

Upvotes: 6

John Kugelman
John Kugelman

Reputation: 362187

Do it the same way you'd invoke ls. You can specify multiple wildcards one after the other:

for file in *.log *.txt

Upvotes: 16

Related Questions