2

I'd like to check to see if a directory contains an array of file extensions. I'm on Ubuntu using Bash.

Something like :

files=$(ls $1/*)

extensions=$( txt pdf doc docx)

if [[ -e $files[@] contains $extenstions[@] ]] && echo "document exists" || 

echo "nothing found"

4 Answers 4

2

Try this:

shopt -s nullglob
files=(*.txt *.pdf *.doc *.docx)
if [[ ${#files} -eq 0 ]]; then echo "nothing found"; fi

or

shopt -s nullglob extglob
files=(*.+(txt|pdf|doc|docx))
if [[ ${#files} -eq 0 ]]; then echo "nothing found"; fi

If you need files from all subdirectories too:

shopt -s nullglob extglob globstar
files=(**/*.+(txt|pdf|doc|docx))
if [[ ${#files} -eq 0 ]]; then echo "nothing found"; fi

From man bash:

nullglob: If set, bash allows patterns which match no files to expand to a null string, rather than themselves.

extglob: If set, the extended pattern matching features are enabled. See below.

globstar: If set, the pattern ** used in a pathname expansion context will match all files and zero or more directories and subdirectories.

Extended globbing:

?(pattern-list): Matches zero or one occurrence of the given patterns

*(pattern-list): Matches zero or more occurrences of the given patterns

+(pattern-list): Matches one or more occurrences of the given patterns

@(pattern-list): Matches one of the given patterns

!(pattern-list): Matches anything except one of the given patterns

-1

find all the files in directory:

 #find all types of files
 PDFS=`find . -type f | grep pdf |wc -l`
 TXTS=`find . -type f | grep txt |wc -l`
 DOCS=`find . -type f | grep doc |wc -l`
 DOCXS=`find . -type f | grep docx |wc -l`
 SUM=$(( PDFS + TXTS + DOCS + DOCXS ))
 if [[ $SUM=0 ]] ; then 
    echo "not found"
 else
    echo "Some document found"

You can do other stuff like that , such as how many documents of type pdf found , or something like that.

You can also use grep -E to write just one expression for counting all types of files , with OR (|) condition. that will reduce to just one command.

Another easy option to count:

   numberoffiles=`find -name "*.pdf" -o -name "*.doc" -o name "*.txt"`
2
  • 1
    find -name "*.pdf" -o -name "*.doc" -o name "*.txt" etc...
    – jasonwryan
    Jan 1, 2016 at 5:51
  • yes , that is even more easy
    – Ijaz Ahmad
    Jan 1, 2016 at 5:55
-1
set   --                             ### init arg array
for e in txt pdf doc docx            ### outer loop for convenience
do    for  f in ./*."$e"             ### inner loop for files
      do   case  $f in (./\*"$e")    ### verify at least one match
           [ -e "$f" ];; esac &&     ### double-verify
           set  "$f" "$@"            ### prepend file to array
done; done                           ### double-done

When that completes all of the files will be in $1 and $2 and etc. The whole group can be referenced as a single string like "$*" or otherwise as a list of separate strings like "$@". The count can be had in "$#". And you can manipulate the arg array members with set (as above) or else w/ shift.

-1

Turn your list of extensions into a @(…|…) wildcard pattern.

shopt -s extglob nullglob
pattern='@('
for x in "${extensions[@]}"; do
  x=${x//"\\"//"\\\\"}; x=${x//"?"//"\\?"}; x=${x//"*"//"\\*"}; x=${x//"["//"\\["}
  pattern="$pattern$x|"
done
pattern="${pattern%\|})"
matches=(*.$pattern)
if ((${#matches[$@]})); then
  echo "There are matches"
fi

Alternatively (especially if you want to find files in subdirectories recursively), use find.

name_patterns=("(")
for x in "${extensions[@]}"; do
  x=${x//"\\"//"\\\\"}; x=${x//"?"//"\\?"}; x=${x//"*"//"\\*"}; x=${x//"["//"\\["}
  name_patterns+=(-name "*.$x" -o)
done
name_patterns[${#name_patterns[@]}]=")"
if [ -n "$(find dir "${name_patterns[@]}" | head -n 1)" ]; then
  echo "There are matches"
fi

Alternatively, use zsh.

matches=(*.$^extensions(NY1))
if ((#matches)); then
  echo "There are matches"
fi

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .