1
#!/bin/bash
#Number for .txt files
txtnum=0
#Number of .sh files
shnum=0

for file in "SOME_PATH";do
  #if file has extension .txt
   if [[ $file ==* ".txt"]]
   then 
    #increment the number of .txt files (txtnum)
    txtnum++
   elif [[ $file ==* ".sh"]]
   then 
    #increment the number of .sh files (shnum)
    shnum++
   fi
echo "Number of files with .txt extension:$txtnum"
echo "Number of files with .sh extension:$shnum"

The above code does not work, but it presents the logic I want it to have.

New to bash, commands might not be right either.

Stefan Skoglund
  • 453
  • 3
  • 5

5 Answers5

2

Since it's been redacted I can't say for sure but SOME_PATH would have to include an unquotted glob * to expand to the files in the directory. Something like:

/path/to/*

Next [[ $file ==* ".txt"]] is not valid, specifically ==* is not a valid comparison operator. You could use =~ to perform regex comparison like [[ $file =~ .*\.txt ]], but personally I would extract the extension first and compare that individually.

Next shnum++ is not valid, you would need to perform that inside of a shell arithmetic (( compound command, such as: ((shnum++))

Finally you are missing a closing done statement for your for loop.


Here is some working code that will accomplish what you need:

#!/bin/bash

txtnum=0
shnum=0

for file in /path/to/files/*; do
    ext="${file##*.}"
    if [[ $ext == txt ]]; then
        ((txtnum++))
    elif [[ $ext == sh ]]; then
        ((shnum++))
    fi
done

printf 'Number of .txt files: %d\n' "$txtnum"
printf 'Number of .sh files: %d\n' "$shnum"
jesse_b
  • 37,005
1

You can generalise this requirement to count as many extensions as you need. For this you will need a shell that supports associative arrays, such as bash.

#!/bin/bash
declare -A exts

for path in "${SOME_PATH-.}"/*
do
    # Only files
    [[ -f "$path" ]] || continue

    # Split off the file component, and then its name and extension
    file=${path##*/}
    name=${file%.*} extn=${file##*.}
    # printf "%s -> %s -> %s %s\n" "$path" "$file" "$name" "$extn"

    # Count this extension type
    (( exts[$extn]++ ))
done

# Here is what we want to know
echo "txt=${exts[txt]-0}, sh=${exts[sh]-0}"
Chris Davies
  • 116,213
  • 16
  • 160
  • 287
0

Try:

#!/bin/bash
txtnum=0
shnum=0

for file in /some/dir/*;do
  if [[ "${file}" =~ \.txt$ ]];then
    txtnum=$((txtnum+1))
  elif [[ "${file}" =~ \.sh$ ]];then
    shnum=$((shnum+1))
  fi
done

echo "Number of files with .txt extention:${txtnum}"
echo "Number of files with .sh extention:${shnum}"
0

One method is to use find(1) and count the number of finds wc(1).

One method to deal with filenames which troublesome characters (newline/space etc) is to have find output for example the i-node number.

#!/bin/bash

txtnum=0
shnum=0
directory=/tmp/somewhere


txtnum=$(/bin/find ${directory} -maxdepth 1 -name '*.txt' -type f -printf "%i\n"|/bin/wc -l)
shnum=$(/bin/find ${directory}  -maxdepth 1 -name '*.sh'  -type f -printf "%i\n"|/bin/wc -l)

echo "Number of .txt files: ${txtnum}"
echo "Number of .sh files: ${shnum}"
Stefan Skoglund
  • 453
  • 3
  • 5
0

Don't loop if you don't have to. Don't loop in the shell unless you're operating on the files.

For a large number of filenames, this will work faster than any other solution proposed thus far:

$ ls /usr/lib | awk -F '[/.]+' \
  '{ ext[$NF]++ } END { for(e in ext){ printf ".%-7s\t%4d\n", e, ext[e]} }' | 
grep -Ew 'so|0' # or extensions of your choice
.0                28
.so               10

Less typing, too!