Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

dalvin200

macrumors 68040
Original poster
Mar 24, 2006
3,473
69
Nottingham, UK
I'm writing a shell script at the moment and its all quite new, and I've been reading around unix.com and google for a good few hours, but can't figure out how to check if a file exists with a certain prefix..

basically i have a directory with some files:
ABC1
ABC2
ABC3
etc..

and want to do:

Code:
if [file exists with prefix ABC*] then
      do something
else
      do something else
fi

and the code in my script looks like:

Code:
if [-e ABC*]; then
     do something
else
     do something else
fi

the thing is ABC files already exist in the directory: ABC1, ABC2 etc.. but it always goes into the ELSE part of the IF statement... :(

even if i hard code the filename to ABC1 which does exist, the IF statement still fails.....

any help from you guys would be really appreciated.

thanks
 
A couple things come to mind. First, you probably want a space between '[' and '-e' as well as 'ABC*' and ']'.

So something like:

Code:
if [ -e ABC* ]; then
     echo "foo"
else
     echo "bar"
fi

Second, be very careful when you're dealing with scripts that operate on relative paths. Either explicitly cd(1) to the directory you need to be in prior to executing your main procedure and verify where you're at or use explicit paths to your files. For the purpose of this example, I will go to /var/tmp and look for my files there.

Third. Unless you're sure that you want to evaluate true if the condition for existence of ABC* as a directory, FIFO, door or any file type other than a plain file, you should probably use '-f' instead of '-e'.

Fourth. Encase your glob expression in quotes. If there are no files that start with ABC you may end up with a script that bombs because nothing is less than a null string.

So:

Code:
cd /var/tmp || exit 255

if [ -f "ABC*" ]; then
     echo "foo"
else
     echo "bar"
fi
 
Hi there RumorMill and thanks for responding..

I have been experimenting a bit and came to realise i should be using the "-f" switch.. like you say..

but it only seems to work on an exact filename

so my code as it stands looks like

Code:
if [ -f "${filePath}/ABC*" ]; then
  blah blah...


still doesn't work.. :(
 
This is because of the way bash performs pathname expansion. You must force the expansion to happen at the right time. This works:

Code:
shopt -s nullglob
x=(ABC*)
if [ -n "$x" ]; then
    echo foo
else
    echo bar
fi

The shopt is there because the default behaviour is that x would simply be ABC* if the pattern doesn't match (unbelievable but true); then x is set to the array of all mathin names; if you leave out the brackets then $x will be the literal ABC*, which doesn't get expanded when you want it to.

HTH,
Sander
 
but it only seems to work on an exact filename

Depending on the shell that you use, you'll get different results. You could tell the shell that you wish to expand with a glob and iterate through the results. Something like this should work:

Code:
#!/bin/sh

cd /var/tmp || exit 255

for i in ABC*; do
     echo "current file is $i"
done

This is obviously less useful if you don't need to do something with each file, but rather just check for the presence of such files. If all you want to do is match a file, do something then exit, you can use a similar approach:

Code:
#!/bin/sh

cd /var/tmp || exit 255

for i in ABC*; do
     echo "saw $i, so doing something..."
     exit 0
done

Note that we're no longer using a test operator, but rather using a loop. If not otherwise specified, shells like Bourne (a.k.a sh(1)) will attempt to look for a file named whatever your expression is.
 
Depending on the shell that you use, you'll get different results. You could tell the shell that you wish to expand with a glob and iterate through the results. Something like this should work:

Code:
#!/bin/sh

cd /var/tmp || exit 255

for i in ABC*; do
     echo "current file is $i"
done

This is obviously less useful if you don't need to do something with each file, but rather just check for the presence of such files. If all you want to do is match a file, do something then exit, you can use a similar approach:

Code:
#!/bin/sh

cd /var/tmp || exit 255

for i in ABC*; do
     echo "saw $i, so doing something..."
     exit 0
done

Note that we're no longer using a test operator, but rather using a loop. If not otherwise specified, shells like Bourne (a.k.a sh(1)) will attempt to look for a file named whatever your expression is.

Thanks for posting this, it just came in handy for me.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.