I'm doing some testing of a product on Apple and Android devices. I'd like a script that will fill up the devices hard drive until 100KB space is left on the drive it's runs against to. Also in linux systems I use dd if=/dev/zero of=zeros bs=1M to fill up the hdd entirely, but.. How do I make it fill up the hdd until certain amount of space is left? I'd like this both for linux command line or a bat script(windows) Example of a shell script and a windows batch script would be the best! Thanks!
-
1First allocate a file for the "reserved" space, then fill the drive. When the drive is full, delete the reserved file. – Daniel R Hicks Dec 10 '13 at 23:51
-
Can please you be more specific ? For example. I want script to fill it up until 100kb is left – Rubynator Dec 10 '13 at 23:57
-
A BAT file with a loop. – Daniel R Hicks Dec 11 '13 at 00:57
2 Answers
Do you need to write a real file, or are dummy files sufficient? The dd method you're using is going to be pretty slow for large drives . . .
In Windows, you can use fsutil file createnew <filename> <length_in_bytes> which will create a filler file. Here's a technet page with some more details.
In linux, fallocate works similarly, e.g. fallocate -l 10G 10gig_filler. Here's a previous SU question on creating filler files, as well as a slightly more technical version on Stack Overflow.
-
3
fallocateactually creates a non-sparse file, but only if your filesystem supports that syscall (otherwise it just fails).ext4andxfsare the only really common filesystems that support it. – jjlin Dec 11 '13 at 00:16 -
In Linux you could do something like this to leave only 1M*:
avail=$( df --output=source,avail -BM | grep sda6 |
awk '{print $NF}' | sed s/M//i); size=$((avail-left) );
fallocate -l $sizeM filler_file;
The trick is parsing df to get the space available and then using fallocate to create a file of the necessary size. However, as @jjlin pointed out, the fallocate call will not work on all filesystems.
You can turn the little script above into a function to make it easier to use and also have it use an alternative method to create the file when on a filesystem that does not support fallocate (though fallocate is much faster and should be preferred where possible). Just add these lines to your ~/.bashrc (or equivalent for other shells):
fill_disk(){
## The space you want left
left=$1
## The unit you are using (Units are K, M, G, T, P, E, Z, Y (powers of 1024) or
## KB, MB, ... (powers of 1000).
unit=$2
## The target drive
disk=$3
## The file name to create, make sure it is on the right drive.
outfile=$4
## The space currently available on the target drive
avail=$(df --output=source,avail -B$unit | grep $disk | awk '{print $NF}' | sed s/$unit//i);
## The size of the file to be created
size=$((avail-left))
## Skip if the available free space is already less than what requested
if [ "$size" -gt 0 ]; then
## Use fallocate if possible, fall back to head otherwise
fallocate -l $size$unit $outfile 2>/dev/null || head -c $size$unit /dev/zero > $outfile
else
echo "There is already less then $left space available on $disk"
fi
}
You can then launch it like this:
fill_disk desired_free_space unit target_disk out_file
For example, to create a file called /foo.txt that will leave only 100M free on / (sda1), run
fill_disk 100 M sda1 /foo.txt
Just make sure the target file is on the drive you want to fill, the function does not check for that.
* I couldn't get it to work reliably for small sizes, either it would run out of space or give me slightly different values from those I requested.
As requested, here's the same thing as a script:
#!/bin/env/bash
left=$1
unit=$2
disk=$3
outfile=$4
avail=$(df --output=source,avail -B$unit | grep $disk | awk '{print $NF}' | sed s/$unit//i);
size=$((avail-left))
if [ "$size" -gt 0 ]; then
fallocate -l $size$unit $outfile 2>/dev/null || head -c $size$unit /dev/zero > $outfile
else
echo "There is already less then $left space available on $disk"
fi
Save it as fill_disk.sh and run like this:
bash fill_disk.sh 100 M sda1 /foo.txt
-
Terdon: Can I use this as a shell script ? So I can use the script on multiple machines without having to modify /.bashrc ? – Rubynator Dec 11 '13 at 19:24
-
@Rubynator sure, just copy everything except the opening
fill_disk(){and closing}into a file and add#!/bin/env/bashto the top of that file and it's a script. – terdon Dec 11 '13 at 19:41 -
Sure but can I still use the parameters like the above example you gave? Please confirm the correct usage. Thanks – Rubynator Dec 11 '13 at 20:10
-
-
-