Як я можу стискати файл на Linux на місці, не використовуючи додаткового місця на диску?


20

У мене накопичувач на 100 ГБ, що має файл 95 ГБ. Мені потрібно звільнити трохи місця на диску (а зараз перенесення файлу з диска - це не варіант). Файл добре стискається з тим gzipчи bz2іншим, але всі ці програми записують стислий файл в окремий файл. У мене не вистачає вільного місця для цього.

Чи є спосіб використання стандартних інструментів стиснення або інших утилітів Unix для стиснення файлу без використання додаткового місця на диску (або принаймні мінімальної кількості додаткового місця на диску)? Я зображую щось, що стискає частину файлу за один раз і записує результати безпосередньо над файлом. Я усвідомлюю, що це було б ризиковано, оскільки файл був би пошкоджений, якщо стиснення було перерване, але я не думаю, що у мене немає вибору.


Одним останнім варіантом, який ми використовували в моєму старому місці, було те, що десь був реж, який містив цілу купу файлів 1G, заповнених сміттям. Потім, якщо ви потрапили на щіпку, ви можете вийняти деякі з них, щоб отримати трохи місця для аварійних ситуацій.

Відповіді:


13

Це доказ концептуального однобанкового руху, але він повинен почати вас. Використовуйте на свій страх і ризик.

truncate -s `gzip -c file | dd of=file conv=notrunc 2>&1 | sed -n '$ s/ .*$// p'` file
mv file file.gz

Це спрацьовує, передаючи дані gz в процес dd, який записує їх назад до того ж файлу. Після завершення файл обрізається до розміру виходу gz.

Це передбачає, що останній рядок випуску dd відповідає:

Скопійовано 4307 байт (4,3 кБ), 2,55855е-05 с, 167 МБ / с

Де перше поле - це ціле число записаних байтів. Це розмір, до якого потрібно буде обрізати файл. Я не на 100% впевнений, що вихідний формат завжди однаковий.


Вишуканий трюк. Чи можете ви пояснити, чому conv=notruncце потрібно?
sleske

Можливо, це не так. gzip -c file | dd of=fileздається, працює так само добре.
користувач710307

1
Люди з пов’язаним питанням спробували це (і я теж його спробував); це взагалі не працює. Здається, він працює лише для дуже невеликих файлів - можливо, тому, що gzip прочитає невеликий файл в оперативній пам’яті, перш ніж стискати його. Для великих файлів (кілька Мб) він не працює, навіть якщо вони стисливі.
sleske

3
Так. Отже, conv = notrunc необхідний.
користувач710307

1
Чи не можливо в будь-який час програма стиснення (наприклад gzip) записує більше байтів заголовка та даних, ніж вихідні байти даних, таким чином перезаписуючи деякі частини файлу? Я думаю, це залежить від обраної програми стиснення. Хтось має ідею, як не допустити цього чи якось (не) ймовірно?
Даніель Бьомер

7

Це не так багато , що gzipі bzip2перезаписати оригінал. Швидше, вони записують стислі дані на диск у вигляді нового файлу, і якщо ця операція успішна, вони від’єднують вихідний нестиснений файл.

Якщо у вас є достатня кількість оперативної пам’яті, ви можете написати сценарій для тимчасового стиснення файлів у tmpfsфайловій системі, після чого видаліть оригінал на диску і замініть його на стиснуту версію. Можливо, щось подібне:

# some distributions mount /dev/shm as tmpfs; replace with bzip2 if you prefer
if gzip -q9c /full/disk/somefile > /dev/shm/somefile.gz
then
    rm -f /full/disk/somefile && mv -i /dev/shm/somefile.gz /full/disk
fi

Зауважте, що ви використовуєте пам'ять, оскільки tmpfsце, по суті, диск RAM. Великий вихідний файл може легко голодувати системою та викликати інші проблеми для вас.


1
Це просто божевільна робота
Ендрю Ламберт

Мені подобається штовхати конверт.
James Sneeringer

3

Не існує жодного інструменту, який працює таким чином, саме з тієї причини, яку ви наводите. Мало хто готовий написати інструмент, який свідомо реалізує ризиковану поведінку.


Я сподівався, що це буде небезпечним, не за замовчуванням варіантом утиліти. Чи можете ви придумати альтернативу? Чи є спосіб усікати файл, наприклад, видалити перші 2 ГБ? Це дозволило б мені використовувати свій обмежений вільний простір для стиснення по черзі, зменшуючи вихідний файл, як я пішов.
Лі

Дійсно не існує жодного розумного способу видалення даних із початку файлу з будь-якої файлової системи, будь-яким інструментом.
Ігнасіо Васкес-Абрамс

2
Але ви можете видалити дані з кінця файлу. Це можна зробити в принципі. Ви зрізаєте дані з кінця файлу, щоб укласти окремі файли, обрізуючи оригінальні файли по ходу. Потім ви стискаєте файли в прямому порядку, видаляючи їх під час руху. Було б болісно реалізовувати, і якщо щось пішло не так, то вас би накрутили. Але це можливо.
Девід Шварц

1

Команди split і csplit можна використовувати для розділення великого файлу на більш дрібні частини, а потім стискання їх окремо. Хоча перегляд монтажу буде досить трудомістким.


Ще один хороший варіант. Можна було б написати якийсь сценарій для цього. Однак це дає безліч окремо стислих файлів, які після повторного стискання потрібно буде знову об'єднати, що не так вже й приємно.
sleske
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.