14

Filling a drive with /dev/urandom seems to be very slow, so I created a file filled with FF:

dd if=/dev/zero ibs=1k count=1000 | tr "\000" "\377" >ff.bin

I'd like to fill the drive with copies of this file but the following command only writes once:

dd if=ff.bin of=/dev/sdb count=10000

How do I fill the drive with copies of the file, or is there a faster way to fill the drive with 1's?

5
  • 6
    Why not use zeros? 1-bits don't erase a disk better than 0-bits. Commented Aug 19, 2014 at 23:08
  • 4
    @Gilles I guess zero is special enough that the disk driver could cheat and not really write anything to disk, only marking blocks as empty. I think some virtual hard disk do so. But still, it depends on which reason he's filling a drive for. If it is security, neither 0 nor 1 are safe enough, and also filling with random wouldn't be good if the hard disk is SSD Commented Aug 21, 2014 at 21:27
  • 2
    @pqnet Zero isn't special for physical storage. With a virtual hard disk, it might be, but filling with anything is unsafe. For SSD, there are specific issues with reallocated blocks, but writing with nonzero values doesn't help with that. Commented Aug 21, 2014 at 21:35
  • @Gilles well, the reason for which he want to write to his disk is not explained so I think it would be great if the question is clarified Commented Aug 21, 2014 at 21:38
  • The venerable dd has a the option seek=N skip N obs-sized blocks at start of output, so you can write a loop to seek to the correct place k*M on the output block device before repeating a write of the M-sized file. Commented Apr 20, 2019 at 13:50

8 Answers 8

18

Simply do:

tr '\0' '\377' < /dev/zero > /dev/sdb

It will abort with an error when the drive is full.

Using dd does not make sense here. You use dd to make sure reads and writes are made of a specific size. There's no reason to do it here. tr will do reads/writes of 4 or 8 kiB which should be good enough.

12
  • 1
    you might even get a boost with tr ... | tee - - - > /dev/disk but the likelihood that tr alone doesn't already meet and exceed the write bottleneck is pretty slim. Commented Aug 19, 2014 at 23:47
  • 1
    @mikeserv, I think the only way to increase performance from that is to reduce the number of system calls made. tee won't help for that. stdbuf -o1M tr... may help. Commented Aug 20, 2014 at 5:41
  • 4
    @mikeserv, actually, using tee - - - does increase throughput significantly in my testing. That's going from 800MiB/s for tr (950MiB/s with stdbuf) to 2.3GiB/s with tee, like you say in any case way above the rate any current drive can sustain. Commented Aug 20, 2014 at 6:01
  • 1
    sorry, how come you pass in '\0' '\377'? Is it necessary? Thanks! Commented Mar 19, 2020 at 12:33
  • 1
    @HCSF Those are the parameters to the tr command. tr translates characters - in this case \0 to \377 - both are octal numbers. /dev/null spews out constant \0 and tr is used to translate that stream into constant \377. 377 in octal is the same as 0xff in hexadecimal. Commented Apr 28, 2021 at 11:30
5

For a faster /dev/urandom alternative, there is shred -v -n 1 (if pseudorandom is OK), or using cryptsetup with random key and zeroing that (for encrypted zeroes). Even without AES acceleration, it easily beats /dev/urandom speeds.

Not sure how fast tr is, otherwise you could just dd if= | tr | dd of=.

Using a file as a pattern source could be done like this:

(while [ 1 ]; do cat file; done) | dd of=...

Although the file should be reasonably large for that to be remotely efficient.

If the count= is important to you, add iflag=fullblock to the dd command. Partial reads are possible which would result in partial blocks to be counted as full blocks. This is especially when using larger blocksizes (like bs=1M), which you should if you want speed.

1
  • shred is fast, and it reports progress! Thanks! Commented Aug 21, 2014 at 16:09
5

I am editing my answer here as I came across a boot disc that didn't even have AWK available (just dd and tr were my only familiar friends available):

dd if=/dev/zero bs=65536 | tr '\0' '\377' | dd of=/dev/sda bs=65536

I found it necessary for speed/performance reasons to choose a 64 kB block size for my disk drive.

The performance of the above command was equal to my first pass of dd if=/dev/zero of=/dev/sda bs=65536 (took about 37 minutes to fill a 75 GiB ATA disk drive, ~35 MiB/s)

3
  • But there are no forks? Commented Apr 20, 2019 at 13:43
  • David, just the single fork to execute AWK, then the control statement loop and printf are function calls of the AWK programming language. Commented Mar 14, 2021 at 20:15
  • fwiw, on my system awk was complaining of a line too long, until I made it 8192 char long instead of 65536 Commented Jan 22, 2022 at 0:06
4
badblocks -v -w -s -b physical block size -t 0xff /dev/the device

Example to write all ff to 4K native HDD at /dev/sdb plus read it back to verify ff was actually written to every block:

$ sudo badblocks -v -w -s -b 4096 -t 0xff /dev/sdb
0

To test the SSD speed, I wrote a little Perl program to write "zeros", "ones" or alphanumerics to a block device given on the command line. It doesn't invoke the dd golem, just does direct writes and syncs. May be of help here:

https://github.com/dtonhofer/wild_block_device_filler

Just run it as

wildly_fill_block_device.pl --dev=sdX1 --fillpat 1 --chunksize=1024P --sync

And it will write 0xFFs to /dev/sdX1 (unbuffered, using Perl's syswrite()) in chunks of (in this case) "1024 physical blocks" while synch-ing the data to disk after every write using fdatasync(). On my SSD, this runs at ~70 MiB/s.

It will ask you whether you are SURE before it proceeds to nuke the partition or disk.

0

You can do it pretty efficiently in Bash without external files, except the device to write to, or external commands, except dd.

  1. Use printf to generate a byte with all one bits, and put it in a Bash variable.
  2. Concatenate the Bash variable to itself multiple times.
  3. Use Bash process substitution to fake an infinitely long input file that repeatedly echoes the Bash variable with no trailing newline.
  4. Use that as the input file to dd.

If you have GNU dd, get a nice progress bar with:

sudo -i
bash
ones="$( printf '\xff' )"; for _ in {1..16}; do ones="$ones$ones"; done; dd status=progress bs=65536 if=<( while true; do echo -n "$ones"; done ) of=/dev/whatever

Remove the status=progress if it doesn't work for you. The 65536 is 216, because the initial byte with all one bits was duplicated 16 times.

0

You can simulate a /dev/one without a special device, with a FIFO + yes:

mkfifo ddfifo
dd if=ddfifo of=<file> iflag=fullblock bs=32K status=progress & yes "" | tr '\n' '\1' > ddfifo

tee may be used to double the throughput:

mkfifo ddfifo
dd if=ddfifo of=<file> iflag=fullblock bs=4M status=progress & yes "" | tr '\n' '\1' | tee ddfifo > ddfifo

If you'd like bytes with all bits set to one, swap '\1' for '\377'.

-2

How to wipe with 1's:

while true; do echo 1 ; done | dd of=/dev/sdX status=progress

How to test the wipe:

dd if=/dev/sdX count=1 bs=512
1
  • That's actually filling with pairs of characters, ASCII/unicode 1 and the subsequent newline. As an aside, you can replace the while loop with yes 1 - but it doesn't address the requirement to fill the drive with the binary bytes 0000001 Commented Jan 22, 2021 at 15:02

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.