Let's say I have a 100 file like this 1.txt ....100.txt. Now I want to remove the .txt and calculate mean of the filename (since they are number). I looked into this Linux: remove file extensions for multiple files but still little confuse.
Asked
Active
Viewed 192 times
-1
-
Is the extension always `.txt`? If so `basename path/to/100.txt .txt` would give you `100` – Ted Lyngmo Oct 27 '21 at 19:24
3 Answers
1
You could use basename <path_to_file> <extension>
to strip away the directory part and extension, which would leave you with only the number.
Example:
#!/bin/bash
shopt -s extglob # extended globbing
filecount=0
sum=0
for file in some_dir/+([0-9]).txt # loop over the files (using extended globbing)
do
num=$(basename "$file" .txt) # strip away dir and extension
(( sum += num )) # sum up the numbers
(( ++filecount )) # count the number of files
done
mean="NaN" # used if filecount is 0
if (( filecount > 0 ))
then
# calculate mean with 2 digits of precision
mean=$(echo "scale=2;$sum/$filecount" | bc)
fi
echo "$mean"

Ted Lyngmo
- 93,841
- 5
- 60
- 108
1
Let's create some sample files:
$ for i in {1..10}; do touch "$RANDOM.txt"; done
$ ls
15158.txt 15964.txt 17123.txt 21123.txt 22209.txt 29456.txt 29826.txt 4168.txt 4287.txt 6787.txt
Now, store the filenames in an array, build up the expression as a string, and send it to a single bc
invocation:
files=(*.txt)
expr="(0"
for f in "${files[@]}"; do expr+=" + ${f%.txt}"; done
expr+=") / ${#files[@]}"
echo "$expr"
echo "scale=3; $expr" | bc
outputs
(0 + 15158 + 15964 + 17123 + 21123 + 22209 + 29456 + 29826 + 4168 + 4287 + 6787) / 10
16610.100
More tersely:
join() { local IFS=$1; shift; echo "$*"; }
files=(*.txt)
printf -v expr "(%s)/%d" "$(join + "${files[@]%.txt}")" ${#files[@]}
echo "$expr"
echo "scale=3; $expr" | bc
(15158+15964+17123+21123+22209+29456+29826+4168+4287+6787)/10
16610.100

glenn jackman
- 238,783
- 38
- 220
- 352
0
I'd do something like this
numbers=`ls | sed 's/.txt//g' | xargs`
echo $numbers
should show "1 2 3 .... 100"
sum=0; count=0
for i in $numbers; do
sum=$(echo "$sum + $i" | bc)
((count++))
done
avg=$(echo "$sum / $count" | bc)
echo $avg

Master SentiBlue
- 25
- 3
-
If the numbers are all integers like it appears to be for OP, you can sum them up in bash and just use bc for the division to find the mean. `sum=$((sum + i))` – Shawn Oct 27 '21 at 20:44