Help - Unix: Check if a file exists with certain prefix

Discussion in 'Mac Programming' started by dalvin200, Jul 29, 2008.

  1. dalvin200 macrumors 68040

    Joined:
    Mar 24, 2006
    Location:
    Nottingham, UK
    #1
    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
     
  2. rumormill macrumors newbie

    Joined:
    Jul 29, 2008
    #2
    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
    
     
  3. dalvin200 thread starter macrumors 68040

    Joined:
    Mar 24, 2006
    Location:
    Nottingham, UK
    #3
    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.. :(
     
  4. Sander macrumors 6502

    Joined:
    Apr 24, 2008
    #4
    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
     
  5. dalvin200 thread starter macrumors 68040

    Joined:
    Mar 24, 2006
    Location:
    Nottingham, UK
    #5
    Thank You

    Thanks for all the help..
    got it all working eventually.. :)
     
  6. rumormill macrumors newbie

    Joined:
    Jul 29, 2008
    #6
    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.
     
  7. randyharris macrumors regular

    Joined:
    Jul 10, 2006
    #7
    Thanks for posting this, it just came in handy for me.
     

Share This Page