How to search a filename stored in a variable using a pattern?

hi,

i have a variable which contains some file names delimited by a single space.

FNAME="s1.txt s2.lst s3.cvs s4.lst"

i have another variable that contains a pattern

FILE_PATTERN="*.lst"

i want to take the filenames from FNAME variable and assign each file name in to an array say
for example:- *.lst will match two files that are s2.lst and s4.lst, so i want to assign s2.lst and s4.lst to a array

FILE[0]="s2.lst"
FILE[1]="s4.lst"

can anyone say how can i do the above.?

Thanks

Made a slight modification to use variable EXTENSION that excludes the *

FNAME="s1.txt s2.lst s3.cvs s4.lst"
#FILE_PATTERN="*.lst"
EXTENSION=".lst"
i=0
echo $FNAME | tr " " "\n"  |grep $EXTENSION | while read LINE
do
 FILE[$i]=$LINE
 i=$(expr $i + 1)
done

thanks for the code.

but in the above code, the array FILE[] is not accessible outside the while loop.
when i try to print FILE[0] and FILE[1] outside the while loop, it shows empty values.

Try displaying the values using below commands.

echo ${FILE[0]}
echo ${FILE[1]}

You may loop through the index to print all the elements.

Yet another way of doing it:

FNAME="s1.txt s2.lst s3.cvs s4.lst"

FILE_PATTERN="lst"
i=0
for f in $FNAME;do
	[ ${f##*.} = $FILE_PATTERN ] && FILE[$i]=$f && i=$((i+1)) 
done

Edited to include ( ) at start and end

$ array=($(echo $FNAME | awk -F[" "] -v var=$(echo $FILE_PATTERN | sed -e 's/*\.//g') '{ORS=" "}{for(i=1;i<=NF;i++){if($i ~ var) print $i}}'))
$ echo ${array[0]}
s2.lst
$ echo ${array[1]}
s4.lst

Your solution is extremely ill-conceived.

Deleting *. utterly changes the meaning of the pattern. A filename that does not match *.ext could match ext , and, vice versa, one that did match could then not match.

It gets worse. sh pattern matching notation and regular expressions are not equivalent. One is not even a subset of the other. Taking sh pattern notation and using it as an AWK regular expression makes no sense.

The parameter expansions of $FNAME and $FILE_PATTERN could trigger pathname expansion (aka file globbing). Unintended globbing of FNAME could lead to items in the output that were not part of the FNAME list. Unintended globbing of FILE_PATTERN could drastically alter the value of var .

The bracketed expression in the awk option argument -F[" "] is also vulnerable to pathname expansion, although the result of such an expansion is identical to the pattern itself, which would alter nothing. Still, it's good to be aware that it could happen.

The echo statements can yield inaccurate output if the argument looks like an option.

Your code may yield correct output in some cases, but it won't work generally.

A correct approach which is also much simpler and more efficient:

a=(`
    set -f
    for i in $FNAME; do
        [[ $i == $FILE_PATTERN ]] && printf ' %s' "$i"
    done
`)

For those who prefer the less-readable one-liner format:

 a=(`set -f; for i in $FNAME; do [[ "$i" == $FILE_PATTERN ]] && printf ' %s' "$i"; done`)

Using case $i in $FILE_PATTERN) ... ;; esac is more portable, but any shell that supports that array syntax also supports [[ ... ]] .

Regards,
Alister

1 Like

a bashism:

echo $FNAME, $FILE_PATTERN 
s1.txt s2.lst s3.cvs s4.lst, *.lst

FILE=( $(echo $FNAME | grep -o "[^ ]"$FILE_PATTERN ))

echo ${FILE[0]}
s2.lst
echo ${FILE[1]}
s4.lst

It's not rock solid, as it does not insist on the dot preceding the extension (dot in FILE_PATTERN is used as a wildcard in grep regex).

Thanks @alister for the lesson of the day. I did realize after posting that it looks way too complicated for the need.