我想从下面的代码中打印正在复制的文件的总大小,而不是单独打印每个复制文件的大小。
#!/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