tags:

views:

97

answers:

8

How would you go about telling whether files of a specific extension are present in a directory, with bash?

Something like

if [ -e *.flac ]; then 
echo true; 
fi 

Thanks

+1  A: 

You need to be carful which flag you throw into your if statement, and how it relates to the outcome you want.

If you want to check for only regular files and not other types of file system entries then you'll want to change your code skeleton to:

if [ -f file ]; then
echo true;
fi

The use of the -f restricts the if to regular files, whereas -e is more expansive and will match all types of filesystem entries. There are of course other options like -d for directories, etc. See http://tldp.org/LDP/abs/html/fto.html for a good listing.

As pointed out by @msw, test (i.e. [) will choke if you try and feed it more than one argument. This might happen in your case if the glob for *.flac returned more than one file. In that case try wrapping your if test in a loop like:

for file in ./*.pdf
do
    if [ -f "${file}" ]; then
    echo 'true';
    break
    fi
done

This way you break on the first instance of the file extension you want and can keep on going with the rest of the script.

dtlussier
except `test` (aka `[`) complains if the pattern expands to more than one file: "binary operator expected" or "too many arguments"
msw
@msw - thanks, I didn't even think of that issue. I've tried to modify my answer to take it into account.
dtlussier
You should quote the variable, i.e. use `"$file"`, because the filename may contain some bad characters, like spaces or asterisks.
Roman Cheplyaka
gotit - thanks.
dtlussier
+1  A: 
#!/bin/bash
files=$(ls /home/somedir/*.flac 2> /dev/null | wc -l)
if [ "$files" != "0" ]
then
echo "Some files exists."
else
echo "No files with that extension."
fi
Ruel
+2  A: 
#!/bin/bash

count=`ls -1 *.flac 2>/dev/null | wc -l`
if [ $count != 0 ]
then 
echo true
fi 
jayrdub
+1  A: 
#/bin/bash

myarray=(`find ./ -maxdepth 1 -name "*.py"`)
if [ ${#myarray[@]} -gt 0 ]; then 
    echo true 
else 
    echo false
fi
birryree
A: 
   shopt -s nullglob
   set -- $(echo *.ext)
    if [ "${#}" -gt 0 ];then
      echo "got file"
    fi
ghostdog74
This is wrong. First, you probably meant `-ge` instead of `-gt`, because otherwise your code won't detect the single file. Second, if there are no files matching the pattern, any conforming shell will left the string `*.ext` untouched, so you still will get one "result".
Roman Cheplyaka
+1  A: 

bash only:

any_with_ext () ( 
    ext="$1"
    any=false
    shopt -s nullglob
    for f in *."$ext"; do
        any=true
        break
    done
    echo $any 
)

if $( any_with_ext flac ); then
    echo "have some flac"
else 
    echo "dir is flac-free"
fi

I use parentheses instead of braces to ensure a subshell is used (don't want to clobber your current nullglob setting).

glenn jackman
+1  A: 
shopt -s nullglob
if [[ -n $(echo *.flac) ]]    # or [ -n "$(echo *.flac)" ]
then 
    echo true
fi
Dennis Williamson
+1  A: 

This uses ls(1), if no flac files exist, ls reports error and the script exits; othewise the script continues and the files maybe be processed

#! /bin/sh
ls *.flac  >/dev/null || exit
## Do something with flac files here
Frayser