18

Я хочу уменьшить размер файла с помощью грубой силы, то есть мне все равно, я просто хочу разрезать файл, скажем, наполовину и отбросить остальные.

Первое, что приходит на ум - это усечение Perl. Я следую примеру на этой странице и сделал то же самое:

seq 9 > test.txt
ls -l test.txt
perl -we 'open( FILE, "< ./test.txt" ) && truncate( FILE, 8 ) && close(FILE);'

Но файл все еще имеет тот же размер:

$ ls -lgG test.txt
-rw-rw---- 1 18 2013-08-08 09:49 test.txt

Как я могу сделать эту работу?

5 ответов5

58

Вы можете использовать команду truncate:

truncate --size=1G test.txt

РАЗМЕР может быть указан как байты, КБ, К, МБ, М и т.д. Я предполагаю, что вы можете вычислить желаемый размер вручную; если нет, вы можете использовать команду stat для получения информации о текущем размере файла.

21
perl -we 'open( FILE, "< ./test.txt" ) && truncate( FILE, 8 ) && close(FILE);'

открывает файл для чтения. Однако для усечения файла вам необходимо изменить его, поэтому дескриптор файла только для чтения не будет работать. Вам нужно использовать режим "изменить" ("+>").

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

Следующее было бы несколько более полезным:

perl -we 'open(FILE, "<", "./test.txt") or die "open: $!";
          truncate(FILE, 8) or die "truncate: $!";
          close(FILE);'

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

2

Вы можете использовать хвост, чтобы сократить до 100000 байт

tail -c 100000 file> file2

-c выводит, начиная с байта 100000 этого файла в этом случае

mv file2 file

заменяет исходный файл только что сгенерированным файлом

1

Ответ выше со ссылкой на усечение хорош. дд также сделает работу:

dd if=test.txt of=test2.txt bs=1 count=8
mv test2.txt test.txt
0

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

#!/bin/bash

LOGDIR=/opt/log
SAVELINES=5000

dirs="$LOGDIR"
for dir in $dirs ; do
    files=${dir}/*
    for f in $files ; do
        echo -e "1,-${SAVELINES}d\nwq" | ed $f 1>/dev/null 2>&1
    done
done

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .