Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Regular Expressions for file name matching

Tags:

regex

bash

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?

like image 285
Mike Avatar asked Nov 29 '10 20:11

Mike


People also ask

What is difference [] and () in regex?

[] denotes a character class. () denotes a capturing group. [a-z0-9] -- One character that is in the range of a-z OR 0-9. (a-z0-9) -- Explicit capture of a-z0-9 .

What does '$' mean in regex?

$ means "Match the end of the string" (the position after the last character in the string). Both are called anchors and ensure that the entire string is matched instead of just a substring.

What does (? I do in regex?

(? i) makes the regex case insensitive. (? c) makes the regex case sensitive.


1 Answers

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

like image 194
thkala Avatar answered Nov 15 '22 22:11

thkala