Best way to split bash into pipe use?

I'm just looking for an easy way to split 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 split it by 3?

The examples I saw do not deal with / in redirection

thanks

+6
source share
4 answers

Using bc :

 $ bc -l <<< "scale=2;$(find . -name '*.mp4' | wc -l)/3" 2.33 

In contrast, the bash shell does only integer arithmetic.

Awk is also very powerful:

 $ find . -name '*.mp4' | wc -l | awk '{print $1/3}' 2.33333 

You don't even need wc when using awk :

 $ find . -name '*.mp4' | awk 'END {print NR/3}' 2.33333 
+19
source

Edit 2018-02-22: Adding shell connector

There is more than one way:

Depending on the required accuracy and the number of calculations must be performed! See shell connector further!

Using bc (binary calculator)

 find . -name '*.mp4' | wc -l | xargs printf "%d/3\n" | bc -l 

or

 echo $(find . -name '*.mp4' | wc -l)/3|bc -l 

or using bash, print only an integer:

 echo $(($(find . -name '*.mp4' | wc -l)/3)) 

Pure

With the recent 64 bits of bash, you can even use @glennjackman's ideas for using globstar , but the calculation of pseudo- globstar can be done with:

 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 

No forks and $res contains a two-digit rounded floating-point value.

Nota strong>. Pay attention to symbolic links when using globstar and ** !

Introducing the shell connector

If you plan to do a lot of calculations, require high precision and use bash , you can use the long-running bc subprocess:

 mkfifo /tmp/mybcfifo exec 5> >(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 remains open and useful:

 ps --sid $(ps ho sid $$) fw PID TTY STAT TIME COMMAND 26035 pts/33 Ss 0:00 bash 26058 pts/33 S 0:00 \_ bash 26059 pts/33 S 0:00 | \_ bc -l 26192 pts/33 R+ 0:00 \_ ps --sid 26035 fw 

Calculation of $PI :

 echo >&5 '4*a(1)' read -u 6 PI echo $PI 3.14159265358979323844 

To complete the subprocess:

 exec 6<&- exec 5>&- 

Small demonstration

Calculation range {1..12} / 42 (I will give you google for answer to the ultimate question of life, the universe, and everything ;)

Regular way

 testBc(){ for ((i=1; i<13; i++)) ;do echo $(bc -l <<<"$i/42"); done } 

Using the lengthy bc subprocess:

 testLongBc(){ mkfifo /tmp/mybcfifo; exec 5> >(bc -l >/tmp/mybcfifo); exec 6< /tmp/mybcfifo; rm /tmp/mybcfifo; for ((i=1; i<13; i++)) ;do echo "$i/42" 1>&5; read -u 6 result; echo $result; done; exec 6>&-; exec 5>&- } 

Look without:

 time testBc .02380952380952380952 .04761904761904761904 .07142857142857142857 .09523809523809523809 .11904761904761904761 .14285714285714285714 .16666666666666666666 .19047619047619047619 .21428571428571428571 .23809523809523809523 .26190476190476190476 .28571428571428571428 real 0m0.084s user 0m0.000s sys 0m0.004s 

Then with:

 time testLongBc .02380952380952380952 .04761904761904761904 .07142857142857142857 .09523809523809523809 .11904761904761904761 .14285714285714285714 .16666666666666666666 .19047619047619047619 .21428571428571428571 .23809523809523809523 .26190476190476190476 .28571428571428571428 real 0m0.012s user 0m0.000s sys 0m0.000s 

Hope the results are the same, but the runtime is very different!

My shell connector

I posted 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 
+8
source

Depending on your version of bash, you don't even need to find this simple task:

 shopt -s nullglob globstar files=( **/*.mp4 ) dc -e "3 k ${#files[@]} 3 / p" 

This method will correctly handle strange edgecase file names containing newlines.

+1
source

find . -name '*.mp4' | wc -l | xargs -I{} expr {} / 2

Best used if you have several outputs that you want to pass through xargs . Use {} as a placeholder for the expression.

+1
source

All Articles