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
  • 443
  • 3
  • 5
  • Thanks for the edit,new to the site,don't know how it works. – Давидко Георгиевв Feb 25 '20 at 14:16
  • 1
    Welcome to the site. Could you please indicate in what way the code does not work? Do you get a specific error message? Can you show us actual console output, and compare it to desired output? If so, please edit your post to include that information; it will make it easier for contributors to help you track down the problem. – AdminBee Feb 25 '20 at 14:16
  • No,the code I wrote is on my phone,and I can't test it . Also i'm quite new to bash,but I understand programming logic,so the code I wrote is code that I'm not sure it works,but I know what logic I want it to have.I don't have my PC with me,but I want to create a working code when I get home. – Давидко Георгиевв Feb 25 '20 at 14:23
  • ls -1 SOME_PATH/*.txt | wc -l – John Hawthorne Feb 25 '20 at 14:26
  • 1
    For simpler and more robust ways to do this, you might want to take a look at [Count files in a directory by extension](https://unix.stackexchange.com/questions/146760/count-files-in-a-directory-by-extension) – steeldriver Feb 25 '20 at 14:50
  • You can check syntax with https://shellcheck.net – roaima Feb 25 '20 at 19:07

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
  • 35,934
  • 12
  • 91
  • 140
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}"
roaima
  • 107,089
  • 14
  • 139
  • 261
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}"
rusty shackleford
  • 2,365
  • 9
  • 21
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
  • 443
  • 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!

James K. Lowden
  • 2,052
  • 13
  • 15