I'm just looking for an easy way to divide a number (or provide other math functions). Let's say I have the following command:
find . -name '*.mp4' | wc -l
How can I take the result of wc -l and divide it by 3?
The examples I've seen don't deal with re-directed out/in.
A pipe in Bash takes the standard output of one process and passes it as standard input into another process. Bash scripts support positional arguments that can be passed in at the command line.
Linux Files, Users, and Shell Customization with Bash If you want to break up a command so that it fits on more than one line, use a backslash (\) as the last character on the line. Bash will print the continuation prompt, usually a >, to indicate that this is a continuation of the previous line.
Using bc
:
$ bc -l <<< "scale=2;$(find . -name '*.mp4' | wc -l)/3" 2.33
In contrast, the bash shell only performs integer arithmetic.
Awk is also very powerful:
$ find . -name '*.mp4' | wc -l | awk '{print $1/3}' 2.33333
You don't even need wc
if using awk
:
$ find . -name '*.mp4' | awk 'END {print NR/3}' 2.33333
Edit 2018-02-22: Adding shell connector
Depending on precision required and number of calcul to be done! See shell connector
further!
bc
(binary calculator)find . -type f -name '*.mp4' -printf \\n | wc -l | xargs printf "%d/3\n" | bc -l 6243.33333333333333333333
or
echo $(find . -name '*.mp4' -printf \\n | wc -l)/3|bc -l 6243.33333333333333333333
or using bash, result in integer only:
echo $(($(find . -name '*.mp4' -printf \\n| wc -l)/3)) 6243
res=000$((($(find . -type f -name '*.mp4' -printf "1+")0)*1000/3)) printf -v res "%.2f" ${res:0:${#res}-3}.${res:${#res}-3} echo $res 6243.33
With recent 64bits bash, you could even use @glennjackman's ideas of using globstar
, but computing pseudo floating could be done by:
shopt -s globstar files=(**/*.mp4) shopt -u globstar res=$[${#files[*]}000/3] printf -v res "%.2f" ${res:0:${#res}-3}.${res:${#res}-3} echo $res 6243.33
There is no fork and $res
contain a two digit rounded floating value.
Nota: Care about symlinks when using globstar
and **
!
shell connector
If you plan to do a lot of calculs, require high precision and use bash, you could use long running bc
sub process:
mkfifo /tmp/mybcfifo exec 5> >(exec bc -l >/tmp/mybcfifo) exec 6</tmp/mybcfifo rm /tmp/mybcfifo
then now:
echo >&5 '12/34' read -u 6 result echo $result .35294117647058823529
This subprocess stay open and useable:
ps --sid $(ps ho sid $$) fw PID TTY STAT TIME COMMAND 18027 pts/9 Ss 0:00 bash 18258 pts/9 S 0:00 \_ bc -l 18789 pts/9 R+ 0:00 \_ ps --sid 18027 fw
Computing $PI
:
echo >&5 '4*a(1)' read -u 6 PI echo $PI 3.14159265358979323844
To terminate sub process:
exec 6<&- exec 5>&-
Computing range {1..157} / 42
( I will let you google for answer to the ultimate question of life, the universe, and everything
;)
... and print 13 result by lines in order to reduce output:
printf -v form "%s" "%5.3f "{,}{,}{,,};form+="%5.3f\n";
By regular way
testBc(){ for ((i=1; i<157; i++)) ;do echo $(bc -l <<<"$i/42"); done }
By using long running bc
sub process:
testLongBc(){ mkfifo /tmp/mybcfifo; exec 5> >(exec bc -l >/tmp/mybcfifo); exec 6< /tmp/mybcfifo; rm /tmp/mybcfifo; for ((i=1; i<157; i++)) ;do echo "$i/42" 1>&5; read -u 6 result; echo $result; done; exec 6>&-; exec 5>&- }
Let's see without:
time printf "$form" $(testBc) 0.024 0.048 0.071 0.095 0.119 0.143 0.167 0.190 0.214 0.238 0.262 0.286 0.310 0.333 0.357 0.381 0.405 0.429 0.452 0.476 0.500 0.524 0.548 0.571 0.595 0.619 0.643 0.667 0.690 0.714 0.738 0.762 0.786 0.810 0.833 0.857 0.881 0.905 0.929 0.952 0.976 1.000 1.024 1.048 1.071 1.095 1.119 1.143 1.167 1.190 1.214 1.238 1.262 1.286 1.310 1.333 1.357 1.381 1.405 1.429 1.452 1.476 1.500 1.524 1.548 1.571 1.595 1.619 1.643 1.667 1.690 1.714 1.738 1.762 1.786 1.810 1.833 1.857 1.881 1.905 1.929 1.952 1.976 2.000 2.024 2.048 2.071 2.095 2.119 2.143 2.167 2.190 2.214 2.238 2.262 2.286 2.310 2.333 2.357 2.381 2.405 2.429 2.452 2.476 2.500 2.524 2.548 2.571 2.595 2.619 2.643 2.667 2.690 2.714 2.738 2.762 2.786 2.810 2.833 2.857 2.881 2.905 2.929 2.952 2.976 3.000 3.024 3.048 3.071 3.095 3.119 3.143 3.167 3.190 3.214 3.238 3.262 3.286 3.310 3.333 3.357 3.381 3.405 3.429 3.452 3.476 3.500 3.524 3.548 3.571 3.595 3.619 3.643 3.667 3.690 3.714 real 0m10.113s user 0m0.900s sys 0m1.290s
Wow! Ten seconds on my raspberry-pi!!
Then with:
time printf "$form" $(testLongBc) 0.024 0.048 0.071 0.095 0.119 0.143 0.167 0.190 0.214 0.238 0.262 0.286 0.310 0.333 0.357 0.381 0.405 0.429 0.452 0.476 0.500 0.524 0.548 0.571 0.595 0.619 0.643 0.667 0.690 0.714 0.738 0.762 0.786 0.810 0.833 0.857 0.881 0.905 0.929 0.952 0.976 1.000 1.024 1.048 1.071 1.095 1.119 1.143 1.167 1.190 1.214 1.238 1.262 1.286 1.310 1.333 1.357 1.381 1.405 1.429 1.452 1.476 1.500 1.524 1.548 1.571 1.595 1.619 1.643 1.667 1.690 1.714 1.738 1.762 1.786 1.810 1.833 1.857 1.881 1.905 1.929 1.952 1.976 2.000 2.024 2.048 2.071 2.095 2.119 2.143 2.167 2.190 2.214 2.238 2.262 2.286 2.310 2.333 2.357 2.381 2.405 2.429 2.452 2.476 2.500 2.524 2.548 2.571 2.595 2.619 2.643 2.667 2.690 2.714 2.738 2.762 2.786 2.810 2.833 2.857 2.881 2.905 2.929 2.952 2.976 3.000 3.024 3.048 3.071 3.095 3.119 3.143 3.167 3.190 3.214 3.238 3.262 3.286 3.310 3.333 3.357 3.381 3.405 3.429 3.452 3.476 3.500 3.524 3.548 3.571 3.595 3.619 3.643 3.667 3.690 3.714 real 0m0.670s user 0m0.190s sys 0m0.070s
Less than one second!!
Hopefully, results are same, but execution time is very different!
shell connector
I've published a connector function: Connector-bash on GitHub.com and shell_connector.sh on my own site.
source shell_connector.sh newConnector /usr/bin/bc -l 0 0 myBc 1764/42 result echo $result 42.00000000000000000000
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With