web-dev-qa-db-ja.com

Linuxでファイルの最初の100MBを切り捨てる

私が言及しているのは 空きディスク容量が非常に少ない2つの巨大なファイルをどのように連結できますか?

私は次のことを実装している最中です:

  1. 結合されたサイズのスパースファイルを割り当てます。
  2. 2番目のファイルの終わりから新しいファイルの終わりまで100Mbをコピーします。
  3. 2番目のファイルの終わりの100Mbを切り捨てます
  4. 2番目のファイルが完成するまで2&3をループします(2.を宛先ファイルの正しい場所に変更します)。
  5. 2&3&4を実行しますが、最初のファイルを使用します。

Linuxで特定のファイルを「切り捨てる」ことができる人がいるかどうか知りたいのですが。切り捨てはファイルサイズによるものです。たとえば、ファイルが10GBの場合、ファイルの最初の100MBを切り捨てて、残りの9.9GBのままにしておきます。誰もがこれを助けることができますか?

ありがとう

20
CheeHow

回答、これはLinuxカーネルv3.15(ext4/xfs)の現実です

ここを読んでください http://man7.org/linux/man-pages/man2/fallocate.2.html

テストコード

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>

#ifndef FALLOC_FL_COLLAPSE_RANGE
#define FALLOC_FL_COLLAPSE_RANGE        0x08
#endif

int main(int argc, const char * argv[])
{
    int ret;
    char * page = malloc(4096);
    int fd = open("test.txt", O_CREAT | O_TRUNC | O_RDWR, 0644);

    if (fd == -1) {
        free(page);
        return (-1);
    }

    // Page A
    printf("Write page A\n");
    memset(page, 'A', 4096);
    write(fd, page, 4096);

    // Page B
    printf("Write page B\n");
    memset(page, 'B', 4096);
    write(fd, page, 4096);

    // Remove page A
    ret = fallocate(fd, FALLOC_FL_COLLAPSE_RANGE, 0, 4096);
    printf("Page A should be removed, ret = %d\n", ret);

    close(fd);
    free(page);

    return (0);
}
19
Sunding Wei

ほとんどのファイルシステムではファイルの先頭を切り落とすことは不可能であり、それを行うための一般的なAPIはありません。たとえば、truncate関数は、ファイルの末尾のみを変更します。

ただし、一部のファイルシステムではそれを実行できる場合があります。たとえば、ext4ファイルシステムは最近、役立つと思われるioctlを取得しました: http://lwn.net/Articles/556136/


更新:この回答が書かれてから約1年後、ext4およびxfsファイルシステム上のファイルの最初と途中からブロックを削除するためのサポートが-に追加されました。 fallocate 関数、FALLOC_FL_COLLAPSE_RANGEモード。低レベルのiotclを自分で使用するよりも便利です。

C関数と同じ名前の コマンドラインユーティリティ もあります。ファイルがサポートされているファイルシステム上にあると仮定すると、これにより最初の100MBが削除されます。

fallocate -c -o 0 -l 100MB yourfile
8
Joni

優れたLinuxプログラミングの本を読んでください。 高度なLinuxプログラミング

Linuxカーネルsyscalls を使用する必要があります。 syscalls(2) を参照してください。

特に truncate(2) (切り捨て用、およびそれをサポートするファイルシステムでスパースファイルを拡張するための両方)、および stat(2) 特にファイルサイズを取得します。

ファイルの先頭(または途中)からバイトを削除する(ポータブルまたはファイルシステムニュートラルな)方法はありません。ファイルの末尾でのみ切り捨てることができます。

バイトではなくASCII行を処理できる場合、ファイルの最初のn行を削除するのは簡単です。たとえば、最初の100行を削除するには:

sed -i 1,100d /path/to/file
2
lyderic

これは今ではかなり古い質問ですが、これが私の見解です。限られたスペースで実行する必要があることを除いて、次のようなものを使用して、ファイルの最初の100MBを切り捨てます。

$ tail --bytes=$(expr $(wc -c < logfile.log) - 104857600) logfile.log > logfile.log.tmp
$ mv logfile.log.tmp logfile.log

説明:

  • これにより、ファイルの最後のnnバイト(tail --bytes)が出力されます。
  • 出力するファイルのバイト数は、ファイルのサイズ(wc -c <logfile.log)から100Mbを引いたもの(expr $(...)-104857600)として計算されます。これにより、ファイルのサイズよりも100Mb小さくなります(例:9.9Gb)
  • 次に、これは一時ファイルに出力され、元のファイル名に戻されて、切り捨てられたファイルが残ります。
1

ファイルから最後の10,000行を除くすべてを削除します。

sed -i 1,$( ( $(wc -l < path/to/file) -10000 ) )d path/to/file 
0
William Yates