Подтвердить что ты не робот

Усечение первого 100 Мбайт файла в Linux

Я имею в виду Как вы можете объединить два огромных файла с очень небольшим запасным дисковым пространством?

Я выполняю следующие действия:

  • Выделите разреженный файл объединенного размера.
  • Скопируйте 100 Мб из конца второго файла в конец нового файла.
  • Усечь 100 Мб конца второго файла
  • Loop 2 & 3 до завершения второго файла (с 2. измененным до нужного места в целевом файле).
  • Сделайте 2 & 3 & 4, но с первым файлом.

Я хотел бы знать, есть ли там кто-нибудь, кто может "обрезать" данный файл в Linux? Усечение осуществляется по размеру файла, например, если файл равен 10 ГБ, я бы хотел усечь первый 100 МБ файла и оставить файл с оставшимся 9,9 ГБ. Кто-нибудь может помочь в этом?

Спасибо

4b9b3361

Ответ 1

Ответ, теперь это реальность с ядром 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);
}

Ответ 2

Отрезать начало файла невозможно в большинстве файловых систем, и нет общего API для этого; например, функция усечения только изменяет окончание файла.

Вы можете сделать это с некоторыми файловыми системами. Например, файловая система ext4 недавно получила ioctl, который может оказаться вам полезным: http://lwn.net/Articles/556136/


Обновление: Примерно через год после написания этого ответа в функцию fallocate была добавлена поддержка удаления блоков из начала и середины файлов в файловых системах ext4 и xfs с FALLOC_FL_COLLAPSE_RANGE режима FALLOC_FL_COLLAPSE_RANGE. Это удобнее, чем использовать iotcl низкого уровня самостоятельно.

Там также утилита командной строки с тем же именем, что и функция C. Если ваш файл находится в поддерживаемой файловой системе, это приведет к удалению первых 100 МБ:

fallocate -c -o 0 -l 100MB yourfile

Ответ 3

Пожалуйста, прочитайте хорошую книгу программирования Linux, например. Расширенное программирование Linux.

Вам нужно использовать ядро ​​Linux syscalls, см. syscalls (2)

В частности truncate (2) (как для усечения, так и для расширения разреженного файла на поддерживаемых им файловых системах) и stat (2), чтобы заметно получить размер файла.

Нет (переносимый или файловой системы) способ удаления байтов с начала (или в середине) файла, вы можете обрезать файл только в конце.

Ответ 4

Если вы можете работать с ASCII-строками, а не с байтами, то удалить первые n строк файла легко. Например, чтобы удалить первые 100 строк:

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

Ответ 5

Это довольно старый вопрос, но вот мой подход к нему. Исключая требование о том, чтобы это было сделано с ограниченным пространством, я использовал бы что-то похожее на следующее, чтобы усечь первый 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) минус 100 Мб (expr $(...) - 104857600). Это оставило бы нас с 100 Мб меньше размера файла, чтобы взять хвост (например, 9.9 ГБ)
  • Затем он выводится в файл temp и затем возвращается к исходному имени файла, чтобы оставить усеченный файл.

Ответ 6

удалить все, кроме последних 10000 строк из файла

sed -i 1, $(($ (wc -l < путь /to/file ) -10000)) d path/to/file