在 bash 中打印复制文件的总大小

在 bash 中打印复制文件的总大小

我想从下面的代码中打印正在复制的文件的总大小,而不是单独打印每个复制文件的大小。

#!/bin/bash
input_folder=/a/b/c
output_folder=/d/e/f

cd $input_folder

for i in *.tiff; do
  size=$(wc -c < ${i})    
  cp -v ${i} $out | sleep 1 | echo -ne "$size%\033[0K\r"
done

bash会每秒打印正在复制的文件的大小。

例如,第二次1它复制file A并打印 的大小file A。其次,2它复制file B并打印文件的大小file B而不是文件的总大小A+B。第二步3它复制file C并打印文件的大小file C而不是文件的总大小A+B+C

具体我该怎么做呢bash

答案1

只需总结单个尺寸echo即可。

#!/bin/bash
input_folder=/a/b/c
output_folder=/d/e/f

cd $input_folder

size_sum=0    
for i in *.tiff; do
  size=$(wc -c < ${i})    
  size_sum=$((size_sum + size))
  cp -v ${i} $out | sleep 1 
done

echo ${size_sum}

答案2

size=$(wc -c < ${i})    

这不是获取文件大小的非常聪明的方法。wc像那样跑步会涉及到阅读整个文件,这实际上是完全没有必要的,因为您想要的只是文件系统已经知道并且可以告诉您的大小。

您随后复制该文件,因此在任何情况下都需要读取该文件,从而缓解了这种情况。中等大小的文件可能会在这段时间内保留在缓存中,因此读取实际上不会到达磁盘。但是,仅读取尺寸似乎还是明智的。

使用 GNU 实用程序,您可以使用stat -c %s "$filename".遗憾的是,其他系统上的选项stat有所不同,我认为没有更好、更便携的方法(除了运行 Perl 之外)

cp -v ${i} $out | sleep 1 | echo -ne "$size%\033[0K\r"

在这里,管道看起来很奇怪。cp不会产生任何输出(到标准输出),至少在没有 的情况下不会产生任何输出-i,因此没有任何内容可以通过管道传输。即使它这样做了,sleep也不会读取任何内容,因此任何输出cp都会被浪费。同样的事情发生在sleep和之间echo。这基本上与管道通常的用途完全相反,但它确实具有所有命令并行运行的效果,并且 shell 等待所有命令完成,因此管道至少需要一秒钟才能运行,不管复制的速度有多快。

$(( .. ))如果您想对文件大小求和,您可能需要shell 的算术扩展。所以,在没有任何额外睡眠的情况下:

dest=/path/to/destination
total=0
for file in *.tiff; do
    size=$(stat -c %s "$file");
    printf "current %d total %d\n" "$size" "$((total += size))"
    cp -- "$file" "$dest"
done

答案3

为了节省脚本中的算术,您可以只获取文件串联的大小:

cat *.tiff | wc

UN*X 内核将与您共同努力,使其与单独获取文件大小一样高效。

答案4

+=如果变量声明为整数,则可以求和:

$ declare -i size
$ size+=100; echo "$size"
100
$ size+=200; echo "$size"
300

您的脚本(正确引用变量扩展):

#!/bin/bash
input_folder=./a/b/c
output_folder=./d/e/f
declare -i size

for i in "$input_folder"/*; do
  size+=$(wc -c < "${i}")    
  cp -v "${i}" "$output_folder" | sleep 1 | echo -ne "$size\033[0K\r"
done

相关内容