我创建了一个 10MB 的测试文件:
dd if=/dev/zero of=file.txt count=1024 bs=10240
然后,我编写了下面的脚本来分块复制此文件。但看起来 dd 没有检测到 EOF,并且它总是返回 0,所以 while 循环会永远持续下去。
#!/bin/sh
block_size=1048576
count=0
retval=0
while true
do
dd if=./file.txt of=other.txt bs=${block_size} seek=${count} skip=${count} status=none
retval=$?
if [[ $retval -ne 0 ]]; then
break
fi
count=$((count + 1))
done
那么,当 dd 超过 EOF 时,如何让它返回差异代码?
答案1
我不知道你为什么需要这个装置;也许是为了学习目的。好的,下面是更复杂的装置:
#!/bin/bash
block_size=1048576 # must be a plain number, without any suffix
count=0
while true
do
retbytes=`dd if=./file.txt bs=$block_size skip=$count count=1 status=none |
tee >(dd of=other.txt bs=$block_size seek=$count status=none) |
wc -c`
[ "$retbytes" -eq "$block_size" ] || break
count=$((count + 1))
done
您的原始脚本使用了sh
和[[
。这不起作用。在我的版本中,[
在需要它的地方就足够了(sh
可以理解),但bash
由于>(…)
其他地方的语法,我无论如何都需要它。
file.txt
您可能没有注意到,但您的脚本在第一遍就处理了整个过程,因为您没有告诉dd
它在第一块之后停止。(注意dd
分块进行,即,您运行的唯一第一个命令dd
会执行您希望整个脚本执行的操作)。稍后,在循环中连续的dd
-s 再次覆盖的次数越来越少(因为它们跳过的次数越来越多);每次都持续到结束file.txt
。它们的工作完全没用(除非在此期间输入文件发生变化)。我认为您的意图是什么count=1
。
我的脚本的工作原理如下:
- 它使用单独的
dd
-s 来表示阅读和写作。 tee
分叉读取的输出dd
。一份副本发送给写入dd
。- 相同的数据到达
wc -c
,此工具会告知其获得的字节数。 - 如果该数字与我们的块大小不匹配,则循环终止。
注意$block_size
必须采用能够与 的输出进行比较的格式。因此,尽管能够理解选项中的一些wc
后缀,但它必须是没有任何后缀的纯数字。dd
bs=