alibek Posted January 25, 2025 Posted January 25, 2025 Есть у меня скрипт, который формирует архив tar.gz. В архиве под миллион файлов, размер порядка 5-6 ГБ. Вначале делается tar, затем архивируется с помощью gzip, по времени занимает около двух минут, работает при этом только одно ядро. Если вместо gzip использовать pigz, то время архивации существенно сокращается (около 10 секунд). Но есть одна странность. Если в файловом менеджере (mc или far) открыть архив, сжатый gzip, то он открывается сравнительно быстро. А вот если открывать архив, сжатый pigz, то нужно ждать секунд 30-40, пока файл-менеджер отобразит содержимое архива. Вот причина таких различий мне не совсем понятна. Вряд ли причина в алгоритмах сжатия, потому что сжатые файлы различаются буквально на доли процента (архив gzip занимает 2932 МБ, архив pigz занимает 2935 МБ). Если фантазировать, то можно предположить, что gzip оглавление каталога пишет в самом начале, а pigz распределяет его по всему файлу (например потому что он многопоточный). Но это именно фантазии, потому что судя по файлу структура у них одинаковая. Нет предположений, почему такая разница? Вставить ник Quote
yandrey Posted January 25, 2025 Posted January 25, 2025 9 часов назад, alibek сказал: отобразит содержимое архива Содержание это же один tar файл, не знаю как в far, а в mc он полностью разжимается, только потом читается tar содержимое, большая разница во времени выполнения может быть только из-за дискового кэша. Вставить ник Quote
alibek Posted January 29, 2025 Author Posted January 29, 2025 На что глаз упал то и выбрал. К тому же gz привычнее и более распространен. Кстати, встретился забавный (нет) глюк с pushd/popd. Скрипт создает временный каталог (mktemp), формирует в нем несколько файлов, потом делает из этих файлов архив и временный каталог удаляется. Архив делался так: tar --verbose --create --file $DST.tar --directory=$TMP . Но был один небольшой недостаток — в архиве создавался каталог ".", а уже внутри него находились файлы. Чтобы этот недостаток обойти, вчера сделал так: pushd -n $TMP ; tar --verbose --create --file $DST.tar * ; popd И оказалось, что звездочка раскрывается не в смененном каталоге, а в текущем (корневом) — и в архив пошло все, пока место на разделе не закончилось. Переделал так: cd $TMP ; tar --verbose --create --file $DST.tar * ; cd $BASE Немного топорно, но зато без побочных эффектов. Вставить ник Quote
Ivan_83 Posted January 29, 2025 Posted January 29, 2025 Короче было написать так: (cd ${TMP} && tar --verbose --create --file ${DST}.tar * ) Вставить ник Quote
st_re Posted January 29, 2025 Posted January 29, 2025 Только не забыть, что * не включает имена с точкой в начале... тоесть если в корне пакуемой директории есть такие имена (файлов или директорий, не важно), то в архив они не попадут... Вставить ник Quote
alibek Posted January 30, 2025 Author Posted January 30, 2025 Действительно, я этот момент упустил из виду. Можно в вызове архиватора указать: tar ... * .* Но если файлов с точкой не будет, то архиватор покажет ошибку. Можно вызывать архиватор дважды и перед вторым вызовом дописать [ -e .* ], но тогда однострочность нарушится. В общем, в моем случае я сам формирую файлы во временном каталоге, файлов с точкой там не будет, так что можно не обращать внимания. А в будущем постараюсь не забыть этот нюанс. Вставить ник Quote
vodz Posted January 30, 2025 Posted January 30, 2025 17 минут назад, alibek сказал: Но если файлов с точкой не будет, то архиватор покажет ошибку. Простите, но .* включает в себя и "." и ".." и в результате у вас в архиве будет текущие файлы, текущий каталог и всё что в предыдущем с вместе с текущем, итого файлы * будут аж три раза. Вставить ник Quote
ixi Posted January 30, 2025 Posted January 30, 2025 (edited) tar -cf 1.tar -C $DIR $(ls -A $DIR) как вариант Edited January 30, 2025 by ixi Вставить ник Quote
alibek Posted January 30, 2025 Author Posted January 30, 2025 Цитата но .* включает в себя и "." и ".." Так я проверил. В Убунте 24 не включает: $ ls -1A 1 2.txt .3 $ echo * .* 1 2.txt .3 А в Убунте 20 включает: $ ls -1A 1 2.txt .3 $ echo * .* 1 2.txt . .. .3 В Убунте 24 в списке опций shopt есть установленная опция globskipdots, возможно это она влияет. (хотя логичнее было бы dotglob, но они одинаковые) Вставить ник Quote
vodz Posted January 30, 2025 Posted January 30, 2025 21 минуту назад, alibek сказал: есть установленная опция globskipdots, возможно это она влияет. Оно, потому и надо ориентироваться на стандарт. Скрипт получится что-то типа: tar cf ../tar.tar -T - < <(find . | while read f; do [ . = "$f" ] && continue; echo "$f"; done) Вставить ник Quote
[anp/hsw] Posted February 3, 2025 Posted February 3, 2025 Что-то вы перемудрили. Почему не: tar cf file.tar -C <нужный каталог> . Или тоже не работает с вашим tar? Вставить ник Quote
alibek Posted February 3, 2025 Author Posted February 3, 2025 Так я же писал. Если указывать ключ --directory (он же -C) и затем в качестве файлов ".", то все архивируется. Но у всех файлов пути прописываются как "./файл", в результате чего некоторые файл-менеджеры при "входе" в такой архив показывают, как будто бы в нем есть каталог ".", а уже в нем файлы. Все эти эксперименты — это чтобы в архиве имена файлов были без каких-либо префиксов. Самое простое — это сменить каталог и указать звездочку — она раскроется в список файлов. С побочными эффектами (в список не войдут файлы, начинающиеся с точки), но в моем случае это несущественно. Вставить ник Quote
ixi Posted February 6, 2025 Posted February 6, 2025 В 03.02.2025 в 11:29, alibek сказал: Но у всех файлов пути прописываются как "./файл", Смотрите мой комментарий выше, как этого избежать. Хотя имхо -- группу файлов всегда лучше архивировать вместе с каталогом. Если необходимо, при разархивировании у tar есть ключ для его пропуска. Вставить ник Quote
alibek Posted February 6, 2025 Author Posted February 6, 2025 Да, советы я прочитал и при необходимости задействую. Но в моем случае это избыточно. Это вспомогательный файл к бэкапу, в котором просто фиксируется вывод текущего состояния: TMP=`mktemp -d` id > $TMP/credentials uname -a > $TMP/os.txt echo >> $TMP/os.txt cat /etc/os-release >> $TMP/os.txt snap list > $TMP/snap.lst ls -1 /snap/bin > $TMP/snap_bin.lst ls -1 /var/lib/snapd/snaps > $TMP/snap_dir.lst apt-mark showmanual &> $TMP/apt.lst apt list --manual-installed &> $TMP/apt_version.lst cd $TMP ; tar --verbose --create --file $DST.tar * ; cd $BASE trap 'rm -rf -- "$TMP"' EXIT [ -n "$ZIP" ] && $ZIP $DST.tar Файлов с точкой там не будет, родительский каталог тоже не нужен. Вставить ник Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.