Как в Вашем примере, можно использовать следующую конструкцию:
mv foo/bar/poit/zoid/{narf.txt,troz.txt}
или даже (как предложенный Ansgar Esztermann):
mv foo/bar/poit/zoid/{narf,troz}.txt
вместо этого ot typing/copypasting долго обращаются дважды.
AFAIK (к сожалению), не возможно усечь файл с начала (это может быть верно для стандартных инструментов, но для syscall уровня, видят здесь). Но с добавлением некоторой сложности можно использовать нормальное усечение (вместе с редкими файлами): можно записать в конец конечного файла не записав все промежуточные данные.
Давайте предположим сначала, что оба файла составляют точно 5 ГиБ (5 120 мебибайт) и что Вы хотите переместить 100 мебибайт за один раз. Вы выполняете цикл, который состоит из
усечение исходного файла одним блоком (освобождающий дисковое пространство)
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
размер блока получающийся файл будет кошмаром фрагментации.
Вместо 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, или Вы потеряете некоторые данные. Если это, то Вы хороши. Я вижу, что он также отметил это ниже.
dmsetup
к виртуальному блочному устройству (который позволяет нормальный, ищут операции, но ни добавляют, ни усекают). Если размер первого файла не является несколькими из 512 затем, необходимо скопировать неполный последний сектор и первые байты из второго файла (в сумме 512) в третий файл. Циклическому устройству для второго файла было бы нужно --offset
затем. А-ч
– Hauke Laging
23.06.2013, 23:30
Необходимо будет записать что-то, что копирует данные в наборах, которые являются самое большее столь же большими как количество свободного пространства, которое Вы имеете. Это должно работать как это:
file2
(использование pread()
путем поиска перед чтением на корректное местоположение).file1
.fcntl(F_FREESP)
освобождать пространство от file2
.fcntl(F_FREESP)
который освобождает пространство, связанное с данным диапазоном байта файла (это делает это редким).
– Celada
23.06.2013, 19:19
fcntl
страница справочника (2012-04-15).
– Hauke Laging
23.06.2013, 19:31
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