No nível de chamada do sistema, isso deve ser possível. Um programa pode abrir seu arquivo de destino para escrever sem truncá-lo e começar a escrever o que ele lê de stdin. Ao ler EOF, o arquivo de saída pode ser truncado.
Como você está filtrando linhas da entrada, a posição de gravação do arquivo de saída deve ser sempre menor que a posição de leitura. Isso significa que você não deve corromper sua entrada com a nova saída.
No entanto, encontrar um programa que faz isso é o problema. dd(1)
tem a opção conv=notrunc
que não trunca o arquivo de saída ao abrir, mas também não trunca no final, deixando o conteúdo do arquivo original após o conteúdo do grep (com um comando como grep pattern bigfile | dd of=bigfile conv=notrunc
)
Como é muito simples a partir de uma perspectiva de chamada do sistema, eu escrevi um pequeno programa e o testei em um sistema de arquivos de loopback completo pequeno (1MiB). Ele fez o que você queria, mas você realmente quer testar isso com alguns outros arquivos primeiro. Sempre será arriscado substituir um arquivo.
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);
}
Você usaria como:
grep pattern bigfile | overwrite bigfile
Estou principalmente postando isso para os outros comentarem antes de você tentar. Talvez alguém saiba de um programa que faz algo semelhante que é mais testado.