GNU/Linux >> Tutoriels Linux >  >> Linux

Manière de modifier un fichier sur place ?

J'ai un fichier assez volumineux (35 Go) et je voudrais filtrer ce fichier in situ (c'est-à-dire que je n'ai pas assez d'espace disque pour un autre fichier), en particulier je veux grep et ignorer certains modèles - existe-t-il un moyen de faire cela sans utiliser un autre fichier ?

Disons que je veux filtrer toutes les lignes contenant foo: par exemple…

Réponse acceptée :

Au niveau de l'appel système, cela devrait être possible. Un programme peut ouvrir votre fichier cible en écriture sans le tronquer et commencer à écrire ce qu'il lit à partir de stdin. Lors de la lecture d'EOF, le fichier de sortie peut être tronqué.

Étant donné que vous filtrez les lignes de l'entrée, la position d'écriture du fichier de sortie doit toujours être inférieure à la position de lecture. Cela signifie que vous ne devez pas corrompre votre entrée avec la nouvelle sortie.

Cependant, trouver un programme qui fait cela est le problème. dd(1) a l'option conv=notrunc qui ne tronque pas le fichier de sortie à l'ouverture, mais il ne le tronque pas non plus à la fin, laissant le contenu du fichier d'origine après le contenu de grep (avec une commande comme grep pattern bigfile | dd of=bigfile conv=notrunc )

Comme c'est très simple du point de vue des appels système, j'ai écrit un petit programme et je l'ai testé sur un petit système de fichiers en boucle complète (1 Mo). Il a fait ce que vous vouliez, mais vous voulez vraiment tester cela avec d'autres fichiers d'abord. Il sera toujours risqué d'écraser un fichier.

écraser.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);
}

Vous l'utiliserez comme :

grep pattern bigfile | overwrite bigfile

Je le poste principalement pour que les autres puissent le commenter avant de l'essayer. Peut-être que quelqu'un d'autre connaît un programme qui fait quelque chose de similaire qui est plus testé.

En relation :Qui est le propriétaire du fichier si le fichier est créé à l'aide de la commande sudo ?
Linux
  1. Un moyen portable d'obtenir la taille du fichier (en octets) dans le shell ?

  2. moyen le plus rapide de convertir un fichier délimité par des tabulations en csv sous Linux

  3. Existe-t-il un moyen de recadrer un fichier NETCDF ?

  4. Comment modifier le fichier DTB du noyau

  5. Existe-t-il un moyen de modifier les raccourcis dans le commandant de minuit ?

Un moyen facile de masquer des fichiers et des répertoires sous Linux

Un moyen facile de fusionner des fichiers avec la commande Cat

Une façon astucieuse de défragmenter un gros système de fichiers ?

Ajouter un fichier exécutable au menu Lubuntu ?

Le moyen le plus sûr de forcer la fermeture d'un descripteur de fichier

Existe-t-il un moyen approprié d'effacer les journaux ?