22

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.

4

4 回答 4

49

使用bc

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

相反,bash shell 只执行整数运算。

awk 也很强大:

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

wc如果使用,您甚至不需要awk

$ find . -name '*.mp4' | awk 'END {print NR/3}'
2.33333
于 2012-11-01T17:13:32.927 回答
10

编辑 2018-02-22:添加shell connector

方法不止一种:

取决于所需的精度要完成的计算次数!进一步看shell connector

使用bc(二进制计算器)

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

或者

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

或使用 bash,只产生整数:

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

纯粹

使用最近的 64 位 bash,您甚至可以使用@glennjackman 的 using 想法globstar但计算伪浮点可以通过以下方式完成:

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

没有分叉并且$res包含一个两位数的四舍五入浮点值。

注意:使用and时注意符号链接globstar**

介绍shell connector

如果您打算进行大量计算,需要高精度并使用,则可以使用长时间运行的bc子进程

mkfifo /tmp/mybcfifo
exec 5> >(exec bc -l >/tmp/mybcfifo)
exec 6</tmp/mybcfifo
rm /tmp/mybcfifo

那么现在:

echo >&5 '12/34'
read -u 6 result
echo $result
.35294117647058823529

此子流程保持开放和可用:

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

计算$PI

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

终止子进程:

exec 6<&-
exec 5>&-

小演示,关于使用管道在 bash 中划分的最佳方法!

计算范围{1..157} / 42(我会让你谷歌搜索answer to the ultimate question of life, the universe, and everything;)

...并逐行打印 13 个结果以减少输出:

printf -v form "%s" "%5.3f "{,}{,}{,,};form+="%5.3f\n";

通过常规方式

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

通过使用长时间运行的bc子进程

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>&-
}

让我们看看没有

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

哇!在我的树莓派上十秒!!

然后

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

不到一秒!!

希望结果是一样的,但执行时间却大不相同!

我的shell connector

我已经发布了一个连接器函数:GitHub.com 上的 Connector-bash 我自己的站点上的 shell_connector.sh

source shell_connector.sh
newConnector /usr/bin/bc -l 0 0
myBc 1764/42 result
echo $result
42.00000000000000000000
于 2012-11-01T17:12:10.680 回答
5

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

如果您有多个要通过管道传输的输出,则最好使用xargs. 用作{}表达式术语的占位符。

于 2016-09-02T14:36:42.110 回答
1

根据您的 bash 版本,您甚至不需要 find 来完成这个简单的任务:

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

此方法将正确处理包含换行符的文件名的奇怪边缘情况。

于 2012-11-01T18:47:41.770 回答