在Unix shell上添加一列数字

Ric*_*dle 185 unix linux shell

给定一个文件列表files.txt,我可以得到这样的大小列表:

cat files.txt | xargs ls -l | cut -c 23-30
Run Code Online (Sandbox Code Playgroud)

产生这样的东西:

  151552
  319488
 1536000
  225280
Run Code Online (Sandbox Code Playgroud)

如何获得所有这些数字的总和

Tod*_*wen 369

... | paste -sd+ - | bc
Run Code Online (Sandbox Code Playgroud)

是我发现的最短的(来自UNIX命令行博客).

编辑:添加了-可移植性的参数,感谢@Dogbert和@Owen.

  • @slf,小心,你刚刚重载`/ usr/bin/sum` (12认同)
  • 'alias sum ="paste -sd + - | bc"`添加到shell完成,谢谢伙伴 (8认同)
  • 当心,某些系统上没有`bc`!另一方面,'awk`是(我相信)POSIX合规性所必需的. (3认同)
  • @donbright,确保输入文件的每一行都包含一个数字,没有其他数字。您可以通过省略`|来调试它 bc`,并目视检查输出以发现语法错误(其格式应为“_a_ + _b_ + _c_ + ...”)。 (2认同)

Gre*_*lds 147

开始

cat files.txt | xargs ls -l | cut -c 23-30 | 
  awk '{total = total + $1}END{print total}'
Run Code Online (Sandbox Code Playgroud)

  • 使用awk是一个好主意,但为什么要保持`cut`?这是一个可预测的列号,所以使用`... | xargs ls -l | awk'{total = total + $ 5} {END {print total}'` (33认同)
  • 为了缩短它,可以使用`total + = $ 1`而不是'total = total + $ 1` (4认同)
  • 你当然是正确的 - 只是追加已经存在的东西更容易:-) (2认同)
  • @ dmckee答案中的一个括号太多了:) (2认同)

ALL*_*ALL 9

如果文件名中有空格,cat将无法工作.这是一个perl单行代替.

perl -nle 'chomp; $x+=(stat($_))[7]; END{print $x}' files.txt
Run Code Online (Sandbox Code Playgroud)


Bar*_*run 8

您可以直接使用而不是使用cutls -l的输出中获取文件大小:

$ cat files.txt | xargs ls -l | awk '{total += $5} END {print "Total:", total, "bytes"}'
Run Code Online (Sandbox Code Playgroud)

Awk将"5美元"解释为第五列.这是来自ls -l的列,它为您提供文件大小.


Col*_*son 7

python3 -c"import os; print(sum(os.path.getsize(f) for f in open('files.txt').read().split()))"
Run Code Online (Sandbox Code Playgroud)


MrM*_*Man 6

如果您没有安装 bc,请尝试

echo $(( $(... | paste -sd+ -) ))
Run Code Online (Sandbox Code Playgroud)

代替

... | paste -sd+ - | bc
Run Code Online (Sandbox Code Playgroud)

$( ) <-- 返回执行命令的值

$(( 1+2 )) <-- 返回评估结果

echo <-- 将其回显到屏幕上


ck *_*ddy 6

cat files.txt | awk '{ total += $1} END {print total}'
Run Code Online (Sandbox Code Playgroud)

您可以使用 awk 执行相同的操作,它甚至会跳过非整数

$ cat files.txt
1
2.3
3.4
ew
1

$ cat files.txt | awk '{ total += $1} END {print total}'
7.7
Run Code Online (Sandbox Code Playgroud)

或者您可以使用 ls 命令并计算人类可读的输出

$ ls -l | awk '{ sum += $5} END  {hum[1024^3]="Gb"; hum[1024^2]="Mb"; hum[1024]="Kb"; for (x=1024^3; x>=1024; x/=1024) { if (sum>=x) { printf "%.2f %s\n",sum/x,hum[x]; break; } } if (sum<1024) print "1kb"; }'
15.69 Mb

$ ls -l *.txt | awk '{ sum += $5} END  {hum[1024^3]="Gb"; hum[1024^2]="Mb"; hum[1024]="Kb"; for (x=1024^3; x>=1024; x/=1024) { if (sum>=x) { printf "%.2f %s\n",sum/x,hum[x]; break; } } if (sum<1024) print "1kb"; }'
2.10 Mb
Run Code Online (Sandbox Code Playgroud)

  • 你甚至不需要管道:`awk '{total += $1} END {print total}'files.txt`更快 (2认同)

And*_*ler 5

如果您只想在没有 awk 或其他解释器的情况下使用 shell 脚本,您可以使用以下脚本:

#!/bin/bash

total=0

for number in `cat files.txt | xargs ls -l | cut -c 23-30`; do
   let total=$total+$number
done

echo $total
Run Code Online (Sandbox Code Playgroud)


小智 5

TMTWWTDI:Perl有一个文件大小运算符(-s)

perl -lne '$t+=-s;END{print $t}' files.txt
Run Code Online (Sandbox Code Playgroud)


小智 5

当你有stat时,整个 ls -l 然后 cut 是相当复杂的。它也容易受到ls -l的确切格式的影响(直到我更改了cut的列号才起作用)

此外,修复了cat无用使用

<files.txt  xargs stat -c %s | paste -sd+ - | bc
Run Code Online (Sandbox Code Playgroud)

  • 呵呵。使用 Unix 32 年了,从来不知道 `&lt;infile command` 和 `command &lt;infile` 是一样的(而且顺序更好)。 (2认同)