Ответы:
Попробуйте ed
вместо этого:
ed <<< $'1d\nwq' large_file
Если это «большой» означает около 10 миллионов строк или более, лучше использовать tail
. Не может редактировать на месте, но его производительность делает этот недостаток простительным:
tail -n +2 large_file > large_file.new
Изменить, чтобы показать некоторые различия во времени:
( awk
добавлен код от Jaypal, чтобы иметь время выполнения на одной машине (процессор 2.2 ГГц).)
bash-4.2$ seq 1000000 > bigfile.txt # further file creations skipped
bash-4.2$ time sed -i 1d bigfile.txt
time 0m4.318s
bash-4.2$ time ed -s <<< $'1d\nwq' bigfile.txt
time 0m0.533s
bash-4.2$ time perl -pi -e 'undef$_ if$.==1' bigfile.txt
time 0m0.626s
bash-4.2$ time { tail -n +2 bigfile.txt > bigfile.new && mv -f bigfile.new bigfile.txt; }
time 0m0.034s
bash-4.2$ time { awk 'NR>1 {print}' bigfile.txt > newfile.txt && mv -f newfile.txt bigfile.txt; }
time 0m0.328s
awk
и получил следующий результат -[jaypal:~/Temp] seq 1000000 > bigfile.txt [jaypal:~/Temp] time awk 'NR>1 {print}' bigfile.txt >newfile.txt real 0m0.649s user 0m0.601s sys 0m0.033s
awk
что производительность будет ближе к sed
. (Примечание для себя: никогда не ожидайте - тестируйте вместо этого.)
tail -n +2 bigfile.txt > bigfile.new && mv -f bigfile.new bigfile.txt;
я использую один файл с блокировкой для отслеживания одного списка задач, используемого несколькими процессами. Я начал с того, что использовали исходный плакат: sed -i 1d large_file
. Это вызывало блокировку файла на 1-2 секунды. tail/mv
Комбо завершает почти мгновенно. Спасибо!
Нет способа эффективно удалить вещи из начала файла. Удаление данных с самого начала требует перезаписи всего файла.
Усечение с конца файла может быть очень быстрым, хотя (операционная система должна только отрегулировать информацию о размере файла, возможно, удаляя теперь неиспользуемые блоки). Обычно это невозможно при попытке удалить из заголовка файла.
Теоретически это может быть «быстро», если вы точно удалили целый блок / экстент, но для этого нет системных вызовов, поэтому вам придется полагаться на семантику, специфичную для файловой системы (если таковая существует). (Или, возможно, с какой-то формой смещения внутри первого блока / экстента, чтобы отметить реальное начало файла, я тоже об этом никогда не слышал.)
Самый эффективный метод, не делайте этого! Если в любом случае вам понадобится вдвое больше «большого» места на диске, вы тратите впустую IO.
Если вы застряли с большим файлом, который хотите прочитать без 1-й строки, подождите, пока вам не понадобится прочитать его для удаления 1-й строки. Если вам нужно отправить файл из stdin в программу, используйте tail для этого:
tail -n +2 | your_program
Когда вам нужно прочитать файл, вы можете воспользоваться возможностью удалить 1-ю строку, но только если у вас есть необходимое место на диске:
tail -n +2 | tee large_file2 | your_program
Если вы не можете читать со стандартного ввода, используйте fifo:
mkfifo large_file_wo_1st_line
tail -n +2 large_file > large_file_wo_1st_line&
your_program -i large_file_wo_1st_line
еще лучше, если вы используете bash, воспользуйтесь заменой процесса:
your_program -i <(tail -n +2 large_file)
Если вам нужен поиск по файлу, я не вижу лучшего решения, чем не застрять с файлом в первую очередь. Если этот файл был сгенерирован stdout:
large_file_generator | tail -n +2 > large_file
Иначе, всегда есть решение подстановки fifo или процесса:
mkfifo large_file_with_1st_file
large_file_generator -o large_file_with_1st_file&
tail -n +2 large_file_with_1st_file > large_file_wo_1st_file
large_file_generator -o >(tail -n 2+ > large_file_wo_1st_file)
Вы можете использовать Vim в режиме Ex:
ex -sc '1d|x' large_file
1
выберите первую строку
d
удалять
x
сохранить и закрыть
Это просто теоретизирование, но ...
Пользовательская файловая система (реализованная с использованием FUSE или аналогичного механизма) может предоставлять каталог, содержимое которого точно совпадает с уже существующим каталогом где-то еще, но с обрезанными по вашему желанию файлами. Файловая система переведет все смещения файла. Тогда вам не нужно будет переписывать файл, требующий много времени.
Но, учитывая, что эта идея очень нетривиальна, если у вас нет десятков терабайт таких файлов, реализация такой файловой системы будет слишком дорогой / трудоемкой, чтобы быть практичной.
tail
, я предпочел бы рассчитывать время , чтобы сделать как удалить первую строку и заменитьbigfile.txt
сbigfile.new
.