Dd (Unix)

dd是一個Unix和類Unix系統上的命令，主要功能為轉換和複製文件。

在Unix上，硬體的設備驅動（如硬碟）和特殊設備文件（如/dev/zero和/dev/random）就像普通文件一樣，出現在文件系統中；只要在各自的驅動程序中實現了對應的功能，`dd`也可以讀取自和/或寫入到這些文件。這樣，`dd`也可以用在備份硬體的引導扇區、取得一定數量的隨機數據等任務中。`dd`程序也可以在複製時處理數據，例如轉換字節序、或在ASCII與EBCDIC編碼間互換。

`dd`的名字可能來源於IBM的工作控制語言（JCL）中的DD語句，意為「Data Description」（數據描述）的縮寫。該命令的語句與JCL中的相似，而與其他Unix命令較不同，因此這可能是個玩笑。另一種解釋是「cc」（根據命令自身的描述，為「convert and copy」（轉換和複製））已經被C語言編譯器（C compiler）所占。

`dd`命令由單一UNIX規範的一部分，IEEE標準1003.1-2008所規定。

## 用法

`dd`的命令行語句與其他的Unix程序不同，因為它的命令行選項格式為`''选项''=''值''`，而不是更標準的`--''选项 值''`或`-''选项''=''值''`。`dd`默認從標準輸入中讀取，並寫入到標準輸出中，但可以用選項`if`（input file，輸入文件）和`of`（output file，輸出文件）改變。

由於作業系統的不同，用法會有出入。另外，`dd`的一些特定功能取決於電腦系統的能力，例如直接訪問記憶體。向運行中的`dd`進程發送SIGINFO信號（Linux上為USR1）可以使它將I/O統計資訊列印到標準錯誤一次，然後繼續複製（注意在OS X上，信號可能導致進程終止）。`dd`可以從鍵盤中讀取標準輸入。到達文件結尾時，`dd`將會退出。信號和EOF是由軟體決定。例如，移植到Windows的Unix工具使用不同的EOF：Cygwin使用 （通常的Unix EOF），而MKS工具箱使用（通常的Windows EOF）。

正如Unix哲學一樣，`dd`只做好一件事（並被認為做得「好」）。與複雜的和高度抽象的實用程序不同，除了為不同的選項做底層決定，`dd`沒有其它的演算法。一般在每一次運行時，會改變`dd`的選項以分步處理一個電腦問題。

## 輸出消息

Linux上GNU coreutils提供的變種沒有描述運行結束時，`dd`輸出到標準輸出消息的格式。然而，其他的實現描述了它，例如BSD上的。

「記錄讀入」和「記錄寫出」行顯示了已完整傳輸的塊數+不完整的塊數，例如物理介質以不完整的塊結尾，或是一個物理錯誤使得一個完整的塊無法被讀取。

## 塊大小

塊是衡量一次讀取、寫入和轉換字節的單位。命令行選項可以為輸入/讀取（`ibs`）和輸出/寫入（`obs`）指定一個不同的塊大小，儘管塊大小（`bs`）選項會覆蓋`ibs`和`obs`選項。輸入和輸出的默認塊大小為512位元組（傳統的磁碟塊及POSIX規定的「塊」大小）複製的`count`選項、讀取的`skip`選項和寫入的`seek`選項都是以塊為單位。轉換操作也受「轉換塊大小」（`cbs`）影響。

在`dd`的一些用途中，塊大小可能會影響表現。例如，當轉換硬碟中數據時，較小的塊大小通常會導致更多的字節被轉換。發出許多小塊的讀取是一種開銷的浪費，且可能會對執行性能有負面影響。較大的塊大小可能會提高複製速度。但是，由於要複製的字節量是由bs×count給出的，因此不可能在一次`dd`命令中複製素數個字節，除非使用兩個糟糕選項之一：`bs=N count=1`（消耗記憶體）或`bs=1 count=N`（大量讀請求開銷）。替代程序（見下文）允許指定字節，而不是塊。在用作網路傳輸時，根據使用的網路協議，塊大小可能會與包大小衝突。

提供給塊大小的值會被解釋成十進位整數，也可以加入後綴指定倍數。後綴`w`表示2倍，`b`表示512倍，`k`表示1024倍，`M`表示1024 × 1024倍，`G`表示1024 × 1024 × 1024倍，等等。另外，在塊大小和計數參數中，一些實現也可以使用`x`表示乘運算。

例如，塊大小`bs=2x80x18b`表示2 × 80 × 18 × 512 = 1474560位元組，也就是一張1440 KiB軟碟的確切大小。

## 用途

`dd`命令可用於各種用途。

### 數據轉換

`dd`可以在文件、設備、分區和卷之間複製數據。數據可以從其中任何地方輸入或輸出；但輸出到分區時有重要差異。此外在傳輸過程中，數據可以用`conv`選項修改以適應介質。

如果最後一個塊有意外長度，試圖使用`cp`複製整個磁碟可能會忽略掉它；然而`dd`卻可能成功。源和目標磁碟應該具有相同的大小。

`dd if=/dev/sr0 of=myCD.iso bs=2048 conv=noerror,sync`｜從CD-ROM中創建ISO磁碟鏡像。

`dd if=/dev/sda2 of=/dev/sdb2 bs=4096 conv=noerror`｜克隆一個分區到另一個。

`dd if=/dev/ad0 of=/dev/ad1 bs=1M conv=noerror`｜克隆硬碟「ad0」到「ad1」。

`noerror`選項意味著如果發生錯誤，程序也將繼續運行。`sync`選項表示填充每個塊到指定字節。

### 備份和恢復主引導記錄

可以修復主引導記錄。主引導記錄可以轉移到文件，或從中轉移出來。

要複製軟碟的前兩個扇區：

```bash
dd if=/dev/fd0 of=MBRboot.img bs=512 count=2
```

要創建整個x86主引導記錄的鏡像（包括MS-DOS分區表和MBR魔法字節）：

```bash
dd if=/dev/sda of=MBR.img bs=512 count=1
```

要創建僅含主引導記錄引導代碼的鏡像（不包括分區表和開機所需的魔法字節）：

```bash
dd if=/dev/sda of=MBR_boot.img bs=446 count=1
```

### 數據修改

`dd`可以原地修改數據。

用空字節覆蓋文件的前512個字節：

```bash
dd if=/dev/zero of=path/to/file bs=512 count=1 conv=notrunc
```

轉換選項`notrunc`意味著不縮減輸出文件，也就是說，如果輸出文件已經存在，只改變指定的字節，然後退出，並保留輸出文件的剩餘部分。沒有這個選項，`dd`將創建一個512位元組長的文件。

在不同的分區中複製磁碟分區到磁碟映像文件中：

```bash
dd if=/dev/sdb2 of=partition.image bs=4096 conv=noerror
```

### 磁碟擦除

出於安全方面的考慮，有時需要擦除丟棄的磁碟。

檢查驅動器上是否有數據，並將其輸出到標準輸出：

```bash
dd if=/dev/sda 
```

用零擦除磁碟：

```bash
dd if=/dev/zero of=/dev/sda bs=4k
```

相較於上面數據修改的例子，不需要使用轉換選項`notrunc`，因為當dd的輸出文件為塊設備時，它沒有效果。

`bs=4k`選項使`dd`一次讀取或寫入4千字節。在現代系統中，由於傳輸容量（如RAID系統），一個更大的塊大小可能更有利。注意用隨機數據填充磁碟總是比用零慢的多，因為隨機數據必須先由CPU和/或HWRNG生成，且不同的設計有不同的性能特點。（後面PRNG的/dev/urandom可能比libc中的要慢。）在大多數較現代的磁碟中，用零擦除會使其中的數據永久丟失。

用零擦除磁碟會使它的數據無法被軟體恢復。然而數據仍可能用特殊的實驗室技術恢復。

shred程序提供了完成相同任務的替代方法，最後，目前許多Linux發行版還提供了一個精心製作的工具wipe（做得「好」，如上面的Unix哲學），提供了更多方法擦除。

### 數據恢復

1984年，GNU `dd`開啟了開源軟體（OSS）恢復數據、文件、驅動器和分區的歷史。`dd`進程一次處理一個塊，它的演算法只是在使用者界面顯示運行狀態。1999年10月，一個C語言的程序`''[http://www.garloff.de/kurt/linux/ddrescue/ dd_rescue]''`發布了。它的演算法一次能處理兩個塊。但改進`dd_rescue`的數據恢復演算法、2003年的shell腳本`[http://www.kalysto.org/utilities/dd_rhelp/index.en.html dd_rhelp]`作者現在推薦`[http://www.gnu.org/software/ddrescue/ddrescue.html GNU ddrescue]`。它是一個發布於2004年的C++程序，與大多數的Linux發行版一起發行。在開源軟體中，GNU `ddrescue`有最先進的塊大小變換演算法。（`ddrescue`和`dd_rescue`儘管名字相近，但卻是不同的程序。因為如此，區分更為明確的備用名稱也有使用；使用的名稱有「addrescue」（freecode.com），「gddrescue」（Debian包名）和「gnu_ddrescue」（openSUSE包名）。）

GNU `ddrescue`既穩定又安全。

另一個開源程序`''savehd7''`使用更複雜的演算法，但它需要安裝自己的語言解釋器。

### 驅動器性能基準測試

對驅動器進行基準測試（通常是單線程），使用1024位元組塊分析連續系統讀取和寫入的性能：

```bash
dd if=/dev/zero bs=1024 count=1000000 of=file_1GB
dd if=file_1GB of=/dev/null bs=1024
```

### 用隨機數據生成文件

使用內核隨機數驅動，用100個隨機字節生成文件：

```bash
dd if=/dev/urandom of=myrandom bs=100 count=1
```

### 將文件轉換為大寫

將文件轉換為大寫：

```bash
dd if=filename of=filename1 conv=ucase
```

### 創建任意大小的空文件

創建1GiB的稀疏文件，或增加現有文件的大小：

```bash
dd if=/dev/zero of=mytestfile.out bs=1 count=0 seek=1G
```

（更先進的工具是GNU coreutils中的fallocate或truncate。）

## 局限

希捷的文檔警告說，「一些依賴底層硬碟訪問的硬碟工具（如DD）可能不支持48位邏輯區塊地址（LBA），除非進行升級」。使用超過128 GiB的ATA硬碟時需要48位LBA。然而在Linux中，`dd`使用內核讀取或寫入原始設備文件。2003年釋出的2.4.23版本內核已經實現了對48位LBA的支持。

有人開玩笑說，`dd`意為「destroy disk」（破壞硬碟）或「delete data」（刪除數據），因為在對硬碟進行底層操作時，類似顛倒輸入和輸出文件的一個小錯誤都可能造成部分或全部硬碟數據的丟失。

## dcfldd

`dcfldd`是`dd`的一個分支，由前美國國防部電腦取證實驗室雇員尼克·哈勃（Nick Harbour）開發的增強版本。與`dd`相比，`dcfldd`允許一個以上的輸出文件，同時支持多種校驗計算方法，還提供了驗證模式以匹配文件，並能顯示操作進度百分比。

## 外部連結

- dd：GNU核心工具組手冊頁。
- 1
- dd for Windows
- savehd7 - Save a potentially damaged harddisk partition
- GNU ddrescue
- GNU ddrescue手冊頁
- dd_rescue
- dd_rhelp
- Softpanorama dd page
- DD at Linux Questions Wiki
- How to use ddrescue to image a damaged harddisk partition and mount it in Windows.
- Forensics (DD) Dcfldd