Answers:
从外观上看,它dd
是IBM操作系统中的一种工具,它保留了其外观(参数传递),该工具执行一些很少使用的功能(例如EBCDIC到ASCII转换或字节序反转……如今不常见)。
我曾经认为这dd
是用于复制大型数据块在同一磁盘上(由于更有效地利用缓存的)速度更快,但是这是不正确的,至少在目前的Linux系统。
我认为某些dd
的选项在处理磁带时很有用,在这种情况下,读取实际上是按块执行的(磁带驱动程序不会像磁盘驱动程序那样将块隐藏在存储介质上)。但我不知道具体情况。
有一两件事dd
可以做,不能(容易)被任何其他POSIX工具所做的是拍摄第一N字节流的。许多系统都可以使用来实现此功能head -c 42
,但是head -c
,尽管很常见,但POSIX中却没有(并且目前在OpenBSD等上不可用)。(tail -c
是POSIX。)而且,即使head -c
存在,它也可能会从源中读取太多字节(因为它在内部使用stdio缓冲),如果您从仅读取会起作用的特殊文件中进行读取,则这是一个问题。(当前的GNU coreutils使用读取确切的计数head -c
,但是FreeBSD和NetBSD使用stdio。)
更一般地,dd
给底层文件的API,它是众多Unix工具独特的接口:仅dd
可覆盖或截断文件在任何时候或寻求在文件中。(这是dd
的独特功能,而且是一项很大的功能;奇怪的dd
是,以其他工具可以做的事情而闻名。)
>
在外壳中也使用重定向时,就会发生这种情况。>>
在外壳中使用重定向或通过将附加到文件的内容tee -a
。如果要通过删除某个点之后的所有数据来缩短文件,则底层内核和C API通过该truncate
功能都支持此功能,但除dd
以下命令外,任何命令行工具都不会公开此功能:
dd if=/dev/null of=/file/to/truncate seek=1 bs=123456 # truncate file to 123456 bytes
同样,如果您想覆盖文件中间的数据,则可以在底层API中通过打开文件进行写入而不会截断(并lseek
在必要时调用以移至所需位置)来实现,但是只能dd
打开文件而不会截断或追加,或从外壳中查找(更复杂的示例)。
# zero out the second kB block in the file (i.e. bytes 1024 to 2047)
dd if=/dev/zero of=/path/to/file bs=1024 seek=1 count=1 conv=notrunc
因此...作为系统工具,dd
几乎没有用。作为文本(或二进制文件)处理工具,它非常有价值!
trunc
并且seek
可以从中使用dd
)。
dd
可以从不可搜索的文件描述符中读取二进制数据,而不会由于stdio缓冲而潜在地破坏未读取的数据。参见此处的示例:etalabs.net/sh_tricks.html
head -c N
调用read
永远不会超过N。在NetBSD 5.1中,head -c
调用是getc
。在FreeBSD 7.4中,head -c
调用fread
。
dd
还向外壳脚本公开了O_DIRECT(等),我认为这也是独一无二的。
该dd
命令包括cat不能容纳的很多选项。也许在您的使用情况下,cat是一种可行的替代品,但它不是dd替代品。
一个示例将dd
用于复制部分内容,而不是整个内容。也许您想根据设备上的已知位置从iso映像的中间部分或硬盘驱动器的分区表中提取一些位。使用dd
可以指定允许执行这些操作的开始,停止和数量选项。
这些选项dd
使它对于细粒度的数据操作必不可少,而cat
*只能对整个文件对象,设备或流进行操作。
*正如Gilles在评论中指出的那样,可以cat
与其他工具组合以隔离某些部分,但cat
仍可以对整个对象进行操作。
dd
实际上与低级设备无关,它需要/dev
像其他设备一样的条目。您可以使用复制整个分区,也可以使用复制cat
一部分tail +c $(($start+1)) | head -c $count
。
cat | head | tail
以获取最后几MB时,磁盘旋转起来会把月亮吸到离地球更近的地方。
还没有人提到您可以使用dd创建稀疏文件,尽管truncate
也可以将其用于相同目的。
dd if=/dev/zero of=sparse-file bs=1 count=1 seek=10GB
这几乎是即时的,并会创建一个任意的大文件,例如,该文件可用作回送文件:
loop=`losetup --show -f sparse-file`
mkfs.ext4 $loop
mkdir myloop
mount $loop myloop
令人高兴的是,它最初仅使用单个磁盘空间块,然后仅根据需要进行扩展(10GB文件的ext4格式在我的系统上消耗291 MB)。使用du
看实际多少磁盘空间使用- ls
仅报告了最大尺寸的文件可能会增长到。
ls -ls
显示稀疏的大小。
dd of=sparse-file bs=1 count=0 seek=10G
相当于truncate -s 10GB sparse-file
。令人困惑的是足够的,truncate
并且dd
有确切的相反的解释GB
与G
...
man dd
说:MB =1000*1000, M =1024*1024
等等。并man truncate
说:MB 1000*1000, M 1024*1024
,所以没有区别。我同时使用GNU coreutils dd
和truncate
GNU coreutils。您也应该这样做!:-)
最近,在我的Linux发行记录中,我第一次有理由克隆了多个GB的多个分区(请参阅cf cp -ar
或对我有用的rsync
很多次)。当然,我转向dd
'cos,每个人都知道那是您使用的...并且对此表现感到震惊。不久之后ddrescue
,我使用了几次谷歌搜索功能,现在我已经使用了几次,并且效果很好(比dd快得多)。
ddrescue
很棒,特别是对于从故障磁盘中获取数据的情况。
这些年来,我想出了一些dd技巧。
如果您未检测到EOF / ^ D / ^ F,则可以使用dd将文本文件传输到主机。因为它将在指定的字节数后自动停止读取。
我是在去年的一次安全演习中使用此功能的,当时我们能够在远程主机上获取非tty shell,并且需要将文件传输进来。
实际上,我什至通过base64对它们进行编码,并使用缓慢但可靠的纯bash base64解码脚本对了几个二进制文件。
dd of=textfile.txt bs=1 count=<size_of_data_in_paste_buffer>
一个超酷的技巧是,在dd运行时,如果向其发送USR1信号,它将发出其当前状态(读取的字节,每秒的字节。)
我编写此代码的目的是,它可以作为任何通过stdout发射数据的程序的纯bash进度过滤器。(注意:几乎所有东西都会通过stdout发出数据-对于不这样做的程序,如果不使用/ dev / stdout作为文件名,则可以欺骗它们,但实际上,每次获得X字节数,打印哈希标记(如启用哈希模式的老式FTP)
(注)进度文件是la脚的,这主要是概念的证明。如果重做,我只会使用一个变量。
dd bs=$BLKSZ of=${TMPFILE} 2>&1 \
| grep --line-buffered -E '[[:digit:]]* bytes' \
| awk '{ print $1 }' >> ${PROGRESS} &
while [[ $(pidof dd) -gt 1 ]]; do
# PROTIP: You can sleep partial seconds
sleep .5
# Force dd to update us on it's progress (which gets
# redirected to $PROGRESS file.
pkill -USR1 dd
local BYTES_THIS_CYCLE=$(tail -1 $PROGRESS)
local XFER_BLKS=$(((BYTES_THIS_CYCLE-BYTES_LAST_CYCLE)/BLKSZ))
if [ $XFER_BLKS -gt 0 ]; then
printf "#%0.s" $(seq 0 $XFER_BLKS)
BYTES_LAST_CYCLE=$BYTES_THIS_CYCLE
fi
done
这是一个极其伪代码的示例,说明如何拥有一个签名的tar文件,该文件可以通过匿名文件句柄提供tar输入而不会出现错误,而无需使用任何tmp文件来存储部分文件数据,而不会出错。
generate_hash() {
echo "yay!"
}
# Create a tar file, generate a hash, append it to the end
tar -cf log.tar /var/log/* 2>/dev/null
TARFILE_SIZE=$(stat -f "%z" log.tar)
SIGNATURE=$(generate_hash log.tar)
echo $SIGNATURE >>log.tar
# Then, later, extract without getting an error..
tar xvf <(dd if=$OLDPWD/log.tar bs=1 count=${TARFILE_SIZE})
tl; dr是:我发现dd非常有用。这些只是我能想到的三个例子。
您可以重定向一些输出内容。如果您需要使用,则它特别有用sudo
:
echo some_content | sudo dd status=none of=output.txt
此外,sudo
它等效于:
echo some_content > output.txt
或对此:
echo some_content | sudo tee output.txt > /dev/null