4

Everyone knows the truncate(file, size) function, which changes the file size to a given size, by truncating the tail of the file. But how to do the same, only with the truncation of not the tail of the file and his head?

Vyacheslav
  • 171
  • 1
  • 8
  • When the file is a logfile and the program writing to it keeps the filedescriptor open, no more logging will appear after moving the file. See https://unix.stackexchange.com/a/122942/57293 – Walter A Feb 11 '19 at 09:04
  • open the file, then `sendfile(fd, fd, &offset, size)`, I test on ubuntu 16, works ok, but the older kernel doesn't support – yuanjianpeng Jul 03 '19 at 06:47

3 Answers3

4

Generally, you have to rewrite the entire file. The simplest way is to skip the first few bytes, copy everything else to a temporary file, and rename the temporary file on top of the old one when done. A more elaborate way is to rewrite it in place, analogous to how memmove works, with read/seek/write/seek or pread/pwrite, and then truncate the last bit when done.

If you are on a recent version of Linux (>= 3.15), and you have a supported filesystem (currently ext4 or xfs), and the amount you wish to remove happens to be a multiple of the filesystem block size, you could use the non-portable fallocate(2) with the FALLOC_FL_COLLAPSE_RANGE flag. Note that this feature is not supported by the portable posix_fallocate.

Nate Eldredge
  • 48,811
  • 6
  • 54
  • 82
3

You could just use tail --lines=<linecount> to always cap the log file to the last linecount lines. This works if you're not trying to truncate to a specific / fixed file size.

cyclone72
  • 31
  • 1
2

The only way is to read the whole file and overwrite it from a needed position.

montonero
  • 1,363
  • 10
  • 16