Wildcard search in if loop

Practice folder contains many files and im interested in extracting file which starts with abc* ghi* xyz* . I need to do variety of operations for different files. if file starts with xyz* then i need to move to some destination otherwise some other destination. I am not able to make wildcard search working in if loop. can someone help me to fix this.

#!/bin/sh
cd /home/practice
for file in abc* ghi* xyz*
 do
  
   if [$file = xyz*];
  then
  #echo $file;
   thetime=`date +%d%M`;
   name=${file%\.*}  
   #echo $name"_"$thetime"."xml
   #mv  ${file}  /test/dest1/$name"_"$thetime"."xml
  else
  #mv  ${file}  /test/dest2/$name"_"$thetime
  
              fi;
 done

can you change the line as follows:

if [[ $file == xyz* ]];

instead of

if [$file = xyz*];

In Bourne shell /bin/sh you will need to extract the heading of the file to test against. The if will only accept a literal value to compare to. You might consider the following:-

#!/bin/sh
cd /home/practice
for file in abc* ghi* xyz*
 do
   testval="${file%${file##???}}"  
   if [ $file = "$testval" ];
  then
:
:

It might look a bit scary, but what the extra line does is to slice up the string. You could do this with cut but that spawns another process, so it can cost a lot of time if this is in a loop for lots of files.

The % and # markers are then followed by descriptions of how to split the line. The second part ${file##???} cuts the first three characters. It seems odd, but given that is what you want, it is the fed back in to the first part which then excludes everything from the string apart from what was worked out in part 2.

So, for a file name of xyz12345678, part 2 evaluates to 12345678, so part 1 the removes this from the end of the whole file name and you are left with xyz You can then use this in your if statement.

I hope that this helps,
Robin
Liverpool/Blackburn
UK

Thanks for your reply but its not working . I think i have not explained the question well or did not understand your explanation. example for file in
/home/practice catalog

abc12_0001_0001
abc13_0001_0002
abc14_0001_0003
ghi12_0001_0001
ghi13_0001_0002
ghi14_0001_0003
xyz12_0001_0001.xml
xyz13_0001_0002.xml
xyz14_0001_0003.xml

Now i want to extract all the files which starting with xyx and move it to some destination. with the code you have given last time

if [ $file = "$testval" ] becomes xyz12_0001_0001=xyz

which is false and it executes the else code. Help me to fix this issue. for now im having a dumb solution

for file in xyz*
 do
   #if [$file] ; 
   thetime=`date +%d%M`;
   name=${file%\.*}
   #echo $name
   #echo $f
   echo $name"_"$thetime"."xml
   mv  ${file}  /test/dest1/$name"_"$thetime"."xml
              #fi;
  done
for file in abc* ghi*
do
  thet=`date +%d%M`;
              echo $file"_"$thet
  #mv  ${file}  /test/dest2/$name"_"$thet
done

thanks for your help in advance

Tested code and it works .

 ls -a
.  ..  abc12_0001_0001  abc13_0001_0002  abc14_0001_0003  ghi12_0001_0001  ghi13_0001_0002  ghi14_0001_0003  xyz12_0001_0001.xml  xyz13_0001_0002.xml  xyz14_0001_0003.xml
code:
#!/bin/bash
mkdir A1 A2
for file in abc* ghi* xyz*
do
if [[ $file == abc* ]];  then
echo "Matched file is: $file";
mv $file "A1"
else
echo "Matching other than abc*"
mv $file "A2"
fi;
done

Two temp dirs are created by the script and after execution , i can see the abc*files in A1 and rest of thefiles in A2.

1 Like

Thanks for your response. Im getting this following error when im running your code

 
`==' is not expected.

I didn't get any error as mentioned earlier it is tested code.
can you post the exact sample data you are trying and code you have used ?

greet_sed, you will notice that kumaar1986 is in the Bourne Shell, so your statement is not valid.

As a demo with my version (and using a case statement to neaten the options):-

$ ls       
abc1216    abc124     abckwefn   xyz116     xyz125     xyzwefwef
abc123     abc125     demo       xyz124     xyz129
$ cat demo 
#!/bin/sh
echo "\n\nSimple if\n"
for file in abc* ghi* xyz*
do
   testval="${file%${file##???}}"  
   if [ "$testval" = "abc" ];
   then
      echo "Found abc file $file"
   fi
   if [ "$testval" = "ghi" ];
   then
      echo "Found ghi file $file"
   fi
   if [ "$testval" = "xyz" ];
   then
      echo "Found xyz file $file"
   fi
done

echo "\n\nUsing a CASE statement\n"
for file in abc* ghi* xyz*
do
   testval="${file%${file##???}}"
   case "$testval" in
     abc) echo "Found abc file $file"   ;;
     ghi) echo "Found ghi file $file"   ;;
     xyz) echo "Found xyz file $file"   ;;
     *)   echo "Found other file $file" ;;
   esac
done

$ demo     


Simple if

Found abc file abc1216
Found abc file abc123
Found abc file abc124
Found abc file abc125
Found abc file abckwefn
Found xyz file xyz116
Found xyz file xyz124
Found xyz file xyz125
Found xyz file xyz129
Found xyz file xyzwefwef


Using a CASE statement

Found abc file abc1216
Found abc file abc123
Found abc file abc124
Found abc file abc125
Found abc file abckwefn
Found other file ghi*
Found xyz file xyz116
Found xyz file xyz124
Found xyz file xyz125
Found xyz file xyz129
Found xyz file xyzwefwef
$ 

You will notice that in the second part, the file ghi* seems to be listed. This is probably because it's actually getting a message about file not found, hence why having the *) clause for the case statement is a good idea. You may want to eith handle the error, ignore it or notify that expected input is missing.

Robin

2 Likes

I cant post the exact data thats y i posted resampled test file names. i rechecked it again and im getting the same error. i tried your exact code and still getting the same error.

@ rbatte1:
Thanks for pointing that.
@kumar:
Try with rbatte1 code if you are using sh instead of bash .

@ rbatte1 thanks a lot. it worked finally. i will go through the code and learn my mistakes. greet_sed thanks a lot for your input. my fault !! i should have mentioned which script im using.

1 Like

We are all here to learn - me just as much as anyone, so I'm happy to have my suggestions criticised and that works well too. I learn more from getting it wrong and having it pointed out.

Thanks for confirming that all is well.

Robin

testval="${file%${file##???}}"

this code splits the first three letters in the file name. How to split the last 3 letters in the code. Im trying to modify the code so i can use the file extension

if[$testval= ".txt"]
do
echo some operation
done
else if [$testval=".xml"]
do
echo some operation
done

can u help me to achieve this operation.
The % and # markers are then followed by descriptions of how to split the line.
Is there any document to learn about how to do this. your help is appreciated

Just reverse what you have:

testval="${file#${file%%???}}"

# works at the front of the string
% works at the end of the string

1 Like

For all these patterns it would need to be tested if a file exists, for example when only moving the files:

for file in abc* ghi* xyz*
do
  if [ -f "$file" ]; then
    case $file in 
      abc*) dest=/path/to/dir1 ;;
      ghi*) dest=/path/to/dir2 ;;
      xyz*) dest=/path/to/dir3 ;;
    esac
    mv -- "$file" "$dest"
  fi
done

Otherwise there will be an error message in case no file with a certain pattern exist..

1 Like

@in2nix4life Thanks your code worked well.@scrutinizer I have used your idea and implemented in my code now. Thanks a lot