Добавьте огромные файлы друг другу, не копируя их

Как в Вашем примере, можно использовать следующую конструкцию:

mv foo/bar/poit/zoid/{narf.txt,troz.txt}

или даже (как предложенный Ansgar Esztermann):

mv foo/bar/poit/zoid/{narf,troz}.txt

вместо этого ot typing/copypasting долго обращаются дважды.

42
24.06.2013, 02:50
4 ответа

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

Давайте предположим сначала, что оба файла составляют точно 5 ГиБ (5 120 мебибайт) и что Вы хотите переместить 100 мебибайт за один раз. Вы выполняете цикл, который состоит из

  1. копирование одного блока от конца исходного файла в конец конечного файла (увеличивающий использованное дисковое пространство)
  2. усечение исходного файла одним блоком (освобождающий дисковое пространство)

    for((i=5119;i>=0;i--)); do
      dd if=sourcefile of=targetfile bs=1M skip="$i" seek="$i" count=1
      dd if=/dev/zero of=sourcefile bs=1M count=0 seek="$i"
    done
    

Но дайте ему попытку с меньшими тестовыми файлами сначала...

Вероятно, файлы не являются ни тем же размером, ни кратными числами размера блока. В этом случае вычисление смещений становится более сложным. seek_bytes и skip_bytes должен использоваться затем.

Если это - способ, которым Вы хотите пойти, но нуждаться в помощи для получения дополнительной информации затем спрашивают снова.

Предупреждение

В зависимости от dd размер блока получающийся файл будет кошмаром фрагментации.

19
27.01.2020, 19:35
  • 1
    Похож это - самый приемлемый способ связать файлы. Спасибо за совет. –  rush 23.06.2013, 22:53
  • 2
    , если нет никакой редкой поддержки файла затем, Вы могли мудрый блоком реверс второй файл на месте и затем просто удалить последний блок и добавляет его к второму файлу –  ratchet freak 24.06.2013, 03:04
  • 3
    я не попробовал это сам (хотя я собираюсь), но seann.herdejurgen.com/resume/samag.com/html/v09/i08/a9_l1.htm является сценарием Perl, который утверждает, что реализовал этот алгоритм. –  zwol 26.11.2013, 19:58

Вместо catting файлы вместе в один файл, возможно, моделируйте единственный файл с именованным каналом, если Ваша программа не может обработать несколько файлов.

mkfifo /tmp/file
cat file* >/tmp/file &
blahblah /tmp/file
rm /tmp/file

Как Hauke предполагает, losetup/dmsetup может также работать. Быстрый эксперимент; я создал 'file1.. file4' и с небольшим количеством усилия, сделал:

for i in file*;do losetup -f ~/$i;done

numchunks=3
for i in `seq 0 $numchunks`; do
        sizeinsectors=$((`ls -l file$i | awk '{print $5}'`/512))
        startsector=$(($i*$sizeinsectors))
        echo "$startsector $sizeinsectors linear /dev/loop$i 0"
done | dmsetup create joined

Затем/dev/dm-0 содержит виртуальное блочное устройство с Вашим файлом как содержание.

Я не протестировал это хорошо.

Другое редактирование: размер файла должен быть делимым равномерно 512, или Вы потеряете некоторые данные. Если это, то Вы хороши. Я вижу, что он также отметил это ниже.

16
27.01.2020, 19:35
  • 1
    Это - прекрасная идея считать этот файл однажды, к сожалению, это не имеет никакой способности перепрыгнуть первым прибыл, первым обслужен назад/вперед, не так ли? –  rush 23.06.2013, 22:50
  • 2
    @rush превосходящая альтернатива может быть должен поместить циклическое устройство на каждый файл и объединить их через dmsetup к виртуальному блочному устройству (который позволяет нормальный, ищут операции, но ни добавляют, ни усекают). Если размер первого файла не является несколькими из 512 затем, необходимо скопировать неполный последний сектор и первые байты из второго файла (в сумме 512) в третий файл. Циклическому устройству для второго файла было бы нужно --offset затем. А-ч –  Hauke Laging 23.06.2013, 23:30
  • 3
    изящные решения. +1 также к Hauke, Отстающему, кто предлагает путь к обходному решению проблема, если бы размер первого файла (файлов) не является несколькими из 512 –  Olivier Dulac 24.06.2013, 21:09

Необходимо будет записать что-то, что копирует данные в наборах, которые являются самое большее столь же большими как количество свободного пространства, которое Вы имеете. Это должно работать как это:

  • Считайте блок данных из file2 (использование pread() путем поиска перед чтением на корректное местоположение).
  • Добавьте блок к file1.
  • Использовать fcntl(F_FREESP) освобождать пространство от file2.
  • Повториться
9
27.01.2020, 19:35
  • 1
    , который я знаю..., но я не мог думать ни о каком пути, который не включил написание кода, и я изобразил запись, что я записал, было лучше что запись ничего. Я не думал о Вашем умном приеме о запуске с конца! –  Celada 23.06.2013, 19:10
  • 2
    Ваш также не работал бы, не начиная с конца, не так ли? –  Hauke Laging 23.06.2013, 19:16
  • 3
    Нет, это работает с начала из-за fcntl(F_FREESP) который освобождает пространство, связанное с данным диапазоном байта файла (это делает это редким). –  Celada 23.06.2013, 19:19
  • 4
    Это довольно прохладно. Но, кажется, очень новая возможность. Это не упоминается в моем fcntl страница справочника (2012-04-15). –  Hauke Laging 23.06.2013, 19:31
  • 5
    @HaukeLaging F_FREESP является Солярис один. На Linux (начиная с 2.6.38), это - флаг FALLOC_FL_PUNCH_HOLE fallocate syscall. Более новые версии fallocate утилиты от util-linux имейте интерфейс к этому. –  Stéphane Chazelas 23.06.2013, 23:12

Я знаю, что это - больше обходного решения, чем, что Вы попросили, но это будет заботиться о Вашей проблеме (и с небольшой фрагментацией или headscratch):

#step 1
mount /path/to/... /the/new/fs #mount a new filesystem (from NFS? or an external usb disk?)

и затем

#step 2:
cat file* > /the/new/fs/fullfile

или, если Вы думаете, что сжатие помогло бы:

#step 2 (alternate):
cat file* | gzip -c - > /the/new/fs/fullfile.gz

Затем (и ТОЛЬКО затем), наконец

#step 3:
rm file*
mv /the/new/fs/fullfile  .   #of fullfile.gz if you compressed it
0
27.01.2020, 19:35
  • 1
    К сожалению, внешний диск usb требует физического доступа, и nfs требует дополнительных аппаратных средств, и у меня нет ничего из него. Так или иначе спасибо. =) –  rush 24.06.2013, 20:58
  • 2
    , я думал, что это был бы тот путь... Ответ Rob Bos затем, что кажется Вашим наилучшим вариантом (не рискуя проигрывающими данными truncating-while-copying, и не поражая ограничения FS также) –  Olivier Dulac 24.06.2013, 21:12

Теги

Похожие вопросы