Truncating a file in Linux means removing its contents while leaving the file itself in place. The file keeps its inode, permissions, and ownership; only the data is gone.
When a service like nginx or syslog is running, it holds an open file descriptor pointing to the file’s inode. If you delete the log file and create a new one, the service keeps writing to the old, deleted inode. The filename is gone but the data is not freed from disk until the service closes that handle. The new file receives no log entries until the process restarts.
Truncating avoids this entirely. The file descriptor stays valid and the process continues writing to the same inode, now empty. For log files managed by active services, truncation is always safer than delete and recreate.
On Bash or Zsh, the shortest method is the > operator used alone:
bash> filename
The shell opens the file for writing, then closes it immediately, producing a zero-byte file. Three equivalent alternatives:
bash: > filename # : is a POSIX builtin that produces no outputcat /dev/null > filename # redirects the empty null deviceecho -n > filename # -n suppresses the newline echo normally adds
All four produce the same result. The bare > is fastest to type interactively; : > filename appears most often in scripts because : is a builtin with no side effects.
Truncating files owned by root. The shell processes > before sudo executes, so this fails:
bashsudo : > /var/log/syslog # fails: Permission denied
Your unprivileged shell opens the file for writing before the elevated process runs. Two workarounds:
bashsudo sh -c '> /var/log/syslog' # spawns a root shell that owns the redirect: | sudo tee /var/log/syslog > /dev/null # pipes nothing to tee as root
sudo sh -c '...' starts a new shell with elevated privileges so the redirect runs inside root’s shell. The tee approach pipes no data through tee, which opens and writes the file as root; the trailing > /dev/null discards tee‘s terminal output.
The truncate command is more explicit and supports sizes other than zero:
bashtruncate -s 0 filename
-s sets the target size. To empty the nginx access log:
bashsudo truncate -s 0 /var/log/nginx/access.log
Set a file to a specific size. Supported suffixes are K, M, G, and T:
bashtruncate -s 100M largefile.img
If the file is smaller than the target, it is extended with null bytes. If it is larger, the extra data is removed and cannot be recovered.
Empty all log files in /var/log at once:
bashsudo truncate -s 0 /var/log/*.log
To include logs in subdirectories, enable globstar first:
bashshopt -s globstarsudo truncate -s 0 /var/log/**/*.log
If the service is actively writing when you truncate, the file will grow back immediately. Use lsof filename to confirm which process has it open and reload or restart the service after truncating. For recurring log management, configure logrotate rather than running manual truncations.
Use > filename for a quick empty at the terminal and truncate -s 0 in scripts where explicit intent matters. Truncation is irreversible — always verify the file path before running. Leave a comment below if you run into any issues.