The answer depends a bit on what file.txt
is, and how process write to it!
I'll cite a common use case : you have a growing logfile called file.txt
, and want to rotate it.
Therefore you copy, for example, file.txt
into file.txt.save
, then truncate file.txt
.
In this scenario, IF the file is not opened by another_process
(ex: another_process
could be a program outputting to that file, for example a program logging something), then your 2 proposals are equivalent, and both work well (but the 2nd is prefered as the first "cat /dev/null > file.txt" is a Useless Use of Cat and also opens and reads /dev/null).
But the real trouble would be if the other_process
is still active, and still has an open handle going to the file.txt.
Then, 2 main cases arise, depending on how other process
opened the file :
If other_process
opens it in the normal way, then the handle will be still pointing to the former location in the file, for example at offset 1200 bytes. The next write will therefore start at offset 1200, and thus you'll have again a file of 1200bytes (+ whatever other_process wrote), with 1200 leading null characters! Not what you want, I presume.
If other_process
opened file.txt
in "append mode", then each time it writes, the pointer will actively seek to the end of the file. Therefore, when you truncate it, it will "seek" until byte 0, and you won't have the bad side effect! This is what you want (... usually!)
Note that this means you need, when you truncate a file, to make sure that all other_process
still writing to that location have opened it in the "append" mode. Otherwise you'll need to stop those other_process
, and start them again, so they start pointing at the beginning of the file instead of the former location.
References : https://stackoverflow.com/a/16720582/1841533 for a cleaner explanation, and a nice short example of difference between normal and append mode logging at https://stackoverflow.com/a/984761/1841533
true
is a shell builtin. – phemmer May 19 '14 at 15:57:
is also mandated by POSIX to be built-in, and in fact is different fromtrue
in that it is considered a "special" built-in. – jw013 May 19 '14 at 16:35>| file
is a more explicit truncate. – tylerl May 19 '14 at 18:40> file
doesn't work incsh
,tcsh
,fish
orzsh
(except in sh/ksh emulation) so I wouldn't say it works in most shells. It works in most shells of the Bourne and rc families. – Stéphane Chazelas May 19 '14 at 19:49true
is not required to be builtin and it traditionally wasn't.:
is built in all the shells of the Bourne family.:
is a special builtin per POSIX (so: > file
will exit the shell for instance iffile
can't be open for writing in POSIX shells) andtrue
is not. POSIX even mentions that:
may be more efficient thantrue
on some systems. – Stéphane Chazelas May 19 '14 at 19:53ksh
hasn't that by default. The POSIX spec is based onksh
, so if it was inksh
, it would be the case in all POSIX shells.set -o noclobber
akaset -C
and>|
are POSIX but not Bourne nor csh, tcsh, rc, es, fish, so you can't really say it's portable. – Stéphane Chazelas May 19 '14 at 20:15true
must bypassPATH
lookup and unless a shell hardcodes a fixed path to an externaltrue
binary, the only way it can meet that requirement is to make the listed utilities built-in. – jw013 May 20 '14 at 21:26true
builtin anyway and like you I don't see the point of executing a hardcoded true, but think of busybox as a possible counter-example. Note that very few shells implement that section of the spec (they generally still run[
orecho
for instance even if they're not found in$PATH
). I find it strange thatfalse
,true
are included in that list and nottype
. – Stéphane Chazelas May 21 '14 at 21:50