Skip to main content
4 of 4
Added public domain notice
camh
  • 40.1k
  • 9
  • 77
  • 62

At the system call level this should be possible. A program can open your target file for writing without truncating it and start writing what it reads from stdin. When reading EOF, the output file can be truncated.

Since you are filtering lines from the input, the output file write position should always be less than the read position. This means you should not corrupt your input with the new output.

However, finding a program that does this is the problem. dd(1) has the option conv=notrunc that does not truncate the output file on open, but it also does not truncate at the end, leaving the original file contents after the grep contents (with a command like grep pattern bigfile | dd of=bigfile conv=notrunc)

Since it is very simple from a system call perspective, I wrote a small program and tested it on a small (1MiB) full loopback filesystem. It did what you wanted, but you really want to test this with some other files first. It's always going to be risky overwriting a file.

overwrite.c

/* This code is placed in the public domain by camh */ #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> int main(int argc, char **argv) { int outfd; char buf[1024]; int nread; off_t file_length; if (argc != 2) { fprintf(stderr, "usage: %s <output_file>\n", argv[0]); exit(1); } if ((outfd = open(argv[1], O_WRONLY)) == -1) { perror("Could not open output file"); exit(2); } while ((nread = read(0, buf, sizeof(buf))) > 0) { if (write(outfd, buf, nread) == -1) { perror("Could not write to output file"); exit(4); } } if (nread == -1) { perror("Could not read from stdin"); exit(3); } if ((file_length = lseek(outfd, 0, SEEK_CUR)) == (off_t)-1) { perror("Could not get file position"); exit(5); } if (ftruncate(outfd, file_length) == -1) { perror("Could not truncate file"); exit(6); } close(outfd); exit(0); } 

You would use it as:

grep pattern bigfile | overwrite bigfile 

I'm mostly posting this for others to comment on before you try it. Perhaps someone else knows of a program that does something similar that is more tested.

camh
  • 40.1k
  • 9
  • 77
  • 62