Another approach - cp
the /dev/null
to the file
xieerqi:$ cat testFile.txt
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/sda1 115247656 83100492 26269816 76% /
none 4 0 4 0% /sys/fs/cgroup
udev 2914492 4 2914488 1% /dev
tmpfs 585216 1152 584064 1% /run
none 5120 0 5120 0% /run/lock
none 2926072 98096 2827976 4% /run/shm
none 102400 76 102324 1% /run/user
xieerqi:$ cp /dev/null testFile.txt
xieerqi:$ cat testFile.txt
xieerqi:$
Why does this work and how does this work ? The testFile.txt
will be opened with O_WRONLY|O_TRUNC
flags, which means if the file exists - it will be truncated, which means contents discarded and size set to zero. This is the same flag with which >
operator in shell opens the file on the right of that operator.
Next, cp
will attempt to read from /dev/null
and after reading 0 bytes will simply close both files, thus leaving testFile.txt
truncated and contents effectively deleted.
Knowing that, we could in theory use anything that allows us to open a file with O_TRUNC
. For instance this:
dd of=testFile.txt count=0
Small difference here is that dd
won't perform any read()
at all. Big plus of this dd
version is that it is POSIXly portable. The dd specifications state:
If the seek= expr conversion is not also specified, the output file shall be truncated before the copy begins if an explicit of= file operand is specified, unless conv= notrunc is specified.
By contrast cp /dev/null testFile.txt
isn't necessarily portable, since POSIX specifications for cp cover what happens only if source_file is non-regular and when -r
/-R
flags are specified (big thanks to Stephen Kitt for pointing this out), but not what happens when -r
or -R
are omitted, which is the case here. However it appears at least GNU cp
defaults to using rule 3 in the same spec, which is truncating the existing file without changing its type.