GNU/Linux >> Linux の 問題 >  >> Linux

ファイルをインプレースで変更する方法は?

かなり大きなファイル(35Gb)があり、このファイルをその場でフィルタリングしたい(つまり、別のファイル用の十分なディスク容量がない)、具体的には、いくつかのパターンをgrepして無視したい-する方法はありますか別のファイルを使用せずにこれを実行しますか?

foo:を含むすべての行を除外したいとします。 たとえば…

承認された回答:

システムコールレベルでは、これが可能であるはずです。プログラムは、ターゲットファイルを切り捨てることなく書き込み用に開き、stdinから読み取ったものの書き込みを開始できます。 EOFを読み取るときに、出力ファイルを切り捨てることができます。

入力から行をフィルタリングしているため、出力ファイルの書き込み位置は常に読み取り位置よりも小さくする必要があります。これは、新しい出力で入力を破損してはならないことを意味します。

ただし、これを行うプログラムを見つけることが問題です。 dd(1) オプションconv=notrunc これは、開いたときに出力ファイルを切り捨てませんが、最後に切り捨てず、grepの内容の後に元のファイルの内容を残します( grep pattern bigfile | dd of =bigfile conv =notrunc

システムコールの観点からは非常に単純なので、小さなプログラムを作成し、小さな(1MiB)フルループバックファイルシステムでテストしました。それはあなたが望むことをしました、しかしあなたは本当に最初に他のいくつかのファイルでこれをテストしたいです。ファイルを上書きするのは常に危険です。

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);
}

次のように使用します:

grep pattern bigfile | overwrite bigfile

私は主に、あなたが試す前に他の人がコメントできるようにこれを投稿しています。おそらく、他の誰かが、よりテストされた同様のことを行うプログラムを知っています。

関連:ファイルがsudoコマンドを使用して作成された場合、ファイルの所有者は誰ですか?
Linux
  1. Linuxでファイルとディレクトリを隠す簡単な方法

  2. シェルでファイルサイズ(バイト単位)を取得するポータブルな方法は?

  3. Linuxでタブ区切りファイルをcsvに変換する最速の方法

  1. inotify を使用する適切な方法は何ですか?

  2. Linux でファイルをコピーする最も効率的な方法

  3. 既存の nautilus (ファイルマネージャ) ブックマークを編集する方法はありますか?

  1. NETCDF ファイルをトリミングする方法はありますか?

  2. ファイルをその場でソートする方法

  3. ファイル変更時の自動バージョン管理 (変更/作成/削除)