Richard Rublev
Richard Rublev

Reputation: 8162

Bash literal match

My script

#!/bin/bash

shopt -s extglob
for i in *.dat;
do
    if [[ "$i" == *(_TEx) ]];then
        file1=$i
    fi
done

echo file1="$file1"

I have tested the script with http://www.shellcheck.net/

$ shellcheck myscript
No issues detected!

Files

262_V01_C00_R000_TEx_BL_2048H.dat
262_V01_C01_R000_TEy_BL_2048H.dat
262_V01_C02_R000_THx_BL_2048H.dat
262_V01_C03_R000_THy_BL_2048H.dat

But

milenko@milenko-HP-Compaq-6830s:~/procmt$ bash a8.sh 
file1=

Why?

Upvotes: 1

Views: 142

Answers (3)

mklement0
mklement0

Reputation: 439767

Tom Fenech's helpful answer and John Kugelman's helpful answer show you effective solutions based on simple globs.

If you want to use extended globbing, as you've attempted (which is not necessary with the sample input):

[[ "$i" == *@(_TEx)* ]]

or, to fold this glob into the loop glob:

for i in *@(_TEx)*.dat; do # ...

Assumes shopt -s extglob, though note that inside [[ ... ]], extended globbing is implicitly turned on in Bash v4.1+ for the RHS of == and !=.


  • Both simple and extended globs match against the entire filename, so *(_TEx) by itself isn't enough - you must provide enclosing * chars. so as to match characters before and after the pattern too.

  • Extended-glob construct *(_TEx) matches zero or more occurrences of _TEx, which effectively matches: (a) the empty string, or (b) any number of repetitions of _TEx; combined with the enclosing * chars., this effectively matches all filenames;
    by contrast, @(_TEx) matches exactly one occurrence of _TEx (but, as demonstrated in the referenced answers, simply including _TEx in a simple glob does the same.).

Upvotes: 2

John Kugelman
John Kugelman

Reputation: 361976

*(_TEx) matches a file name that consists solely of the string _TEx repeated over and over, as in _TEx_TEx_TEx_TEx.

What you're looking for is *_TEx*, no extended glob needed. And then you can combine this with the *.dat glob and get rid of the loop entirely.

echo *_TEx*.dat

Upvotes: 3

Tom Fenech
Tom Fenech

Reputation: 74685

The minimal modification to your attempt to make it work would be this:

    if [[ "$i" == *_TEx* ]]; then

i.e. remove the parentheses and add the missing * at the end of the pattern. There's no need to set the extglob shell option, as you don't need to use any of its features.

However, you might as well change the glob that your are looping over to this:

for i in *_TEx*.dat;

and avoid the if entirely.

Better yet, you could just print the matches directly:

shopt -s nullglob
printf '%s\n' *_TEx*.dat # print all files matching the pattern

nullglob is useful here as it will result in no output when no files match the pattern.

Upvotes: 4

Related Questions