我們在測試或調試的時候,有時候會需要產生某個size的檔案,比如在測試儲存系統時,需要將磁碟剩餘空間減少5G,最簡單的辦法就是拷貝一個5G的檔案過來,但是從哪兒去弄這樣大小的檔案呢,或許你想到隨便找一個檔案,不停的拷貝,最後合并,這也不失為一種辦法,但是有了dd,你會更容易且更靈活的實現。
我們來case by case的介紹dd的用法。先看第一個
產生一個大小為5G的檔案,內容不做要求
命令如下
複製代碼 代碼如下:
$ dd if=/dev/zero of=tmp.5G bs=1G count=5
解釋一下這裡用到的參數
複製代碼 代碼如下:
if=FILE : 指定輸入檔案,若不指定則從標註輸入讀取。這裡指定為/dev/zero是Linux的一個偽檔案,它可以產生連續不斷的null流(二進位的0)
of=FILE : 指定輸出檔案,若不指定則輸出到標準輸出
bs=BYTES : 每次讀寫的位元組數,可以使用單位K、M、G等等。另外輸入輸出可以分別用ibs、obs指定,若使用bs,則表示是ibs和obs都是用該參數
count=BLOCKS : 讀取的block數,block的大小由ibs指定(只針對輸入參數)
這樣上面產生5G檔案的命令就很好理解了,即從/dev/null每次讀取1G資料,讀5次,寫入tmp.5G這個檔案
再看下面一個問題
複製代碼 代碼如下:
將file.in的前1M追加到file.out的末尾
命令如下
複製代碼 代碼如下:
$ file_out_size=`du -b file.out | awk '{print $1}'`
$ dd if=./file.in ibs=1M count=1 of=./file.out seek=1 obs=$file_out_size
這裡ibs和obs設定為了不同的值,和前面的命令相比,只多了一個seek參數
複製代碼 代碼如下:
seek=BLOCKS : 在拷貝資料之前,從輸出檔案開頭跳過BLOCKS個block,block的大小由obs指定
命令的意思就是從file.in讀取1個1M的資料區塊寫入file.out,不過寫入位置並不在file.out的開頭,而是在1*$file_out_size位元組位移處(也就是檔案末尾)
在此基礎上再增加一個要求
將file.in的第3M追加到file.out的末尾
複製代碼 代碼如下:
$ file_out_size=`du -b file.out | awk '{print $1}'`
$ dd if=./file.in skip=2 ibs=1M count=1 of=./file.out seek=1 obs=$file_out_size
這裡多了一個參數skip
複製代碼 代碼如下:
skip=BLOCKS : 拷貝資料前,從輸入檔案跳過BLOCKS個block,block的大小由ibs指定。這個參數和seek是對應的
上面命令的意思就是,從檔案file.in開始跳過2*1M,拷貝1*1M資料,寫入檔案file.out的1*$file_out_size位移處
這樣基本的參數都介紹全了,無非就是設定輸入輸出檔案以及各自的位移,設定讀寫資料區塊大小和讀取資料區塊個數,下面總結一下
複製代碼 代碼如下:
輸入參數:
if
skip
ibs
count
輸出參數:
of
seek
obs
最後來一道終極題。前面建立的都是null流,這次換一個
複製代碼 代碼如下:
指定某個字元,建立一個全是這個字元的指定大小的檔案。比如建立一個檔案,大小為123456位元組,每個位元組都是字元A
這問題看似沒什麼意義,但有時候確實需要用到。比如我通過/dev/null建立了一個1G的檔案,但是出於測試需求我想修改中間100M資料,這時我需要建立一個100M的檔案,將該檔案寫入到那個1G檔案的指定位置,而這個100M的檔案是不能從/dev/null建立的,否則達不到修改的目的,這時候就需要這樣的功能了
話不多說,直接上指令碼,有了前面的基礎,相信都能看得懂
複製代碼 代碼如下:
#!/bin/bash
if [ $# -ne 3 ];then
echo "usage : $0 character out_file file_size(Byte)"
exit 1
fi
echo "$1" | grep -q "^[a-zA-Z]$"
if [ $? -ne 0 ];then
echo "arg1 must be character"
exit 1
fi
character=$1
out_file=$2
target_size=$3
# echo輸出預設是帶'\n'字元的,所以需要通過dd指定輸入位元組數
echo "$character" | dd of=$out_file ibs=1 count=1
while true
do
cur_size=`du -b $out_file | awk '{print $1}'`
if [ $cur_size -ge $target_size ];then
break
fi
remain_size=$((target_size-$cur_size))
if [ $remain_size -ge $cur_size ];then
input_size=$cur_size
else
input_size=$remain_size
fi
dd if=$out_file ibs=$input_size count=1 of=$out_file seek=1 obs=$cur_size || exit 1
done
有了這些技巧,在對檔案內容無要求的前提下,你就可以任意建立指定大小的檔案,任意修改檔案指定位元組數,這會讓某些測試場合變得非常方便