Как заархивировать большое количество подкаталогов -, чтобы каждый zip-файл содержал N подкаталогов -

Да, это возможно. См.https://askubuntu.com/questions/92019/how-to-install-specific-ubuntu-packages-with-exact-version

Короче говоря, если вы хотите обновить fooдо версии 2.5, вместо запуска apt upgrade fooвы должны запуститьapt upgrade foo=2.5

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

2
12.03.2021, 08:59
2 ответа

Итак, я предполагаю, что все подкаталоги -, которые вы хотите сгруппировать, находятся точно на одном уровне глубины под вашим родительским каталогом. Мы позволим zipвернуться в каталоги sub -sub -.

РЕДАКТИРОВАТЬ:Благодаря предложениям людей, эта новая версия теперь работает со всеми типами имен файлов, включая имена, содержащие пробелы, новые строки и специальные символы. Отличную статью по этому поводу можно найти здесь :.https://unix.stackexchange.com/a/321757/439686

#!/bin/bash
export rootdir=${1:-/your/parent/directory}
export N=10 # group size
export stamp=$(date +%s)

find "$rootdir" -type d -mindepth 1 -maxdepth 1  -exec bash -c '
   count=0 # group number
   while [ $# -gt 0 ] ;do
     ((count++))
     zip -r "$rootdir/group.${stamp}.${count}.zip" "${@:1:N}"
     shift $N || set --
   done
' "" {} +

Результат:

group.1615512971.1.zip
group.1615512971.2.zip
group.1615512971.3.zip
group.1615512971.4.zip
...

А вот немного другая версия, которая также перебирает позиционные параметры, но без порождения подоболочки. (Эта версия работает быстрее предыдущей)

#!/bin/bash
rootdir=/your/parent/directory
N=10 # group size
stamp=$(date +%s)

readarray -td '' ARRAY < <(find "$rootdir" -type d -mindepth 1 -maxdepth 1 -print0)
set -- "${ARRAY[@]}"

count=0
while [ $# -gt 0 ] ;do
  ((count++))
  zip -r "$rootdir/group.${stamp}.${count}.zip" "${@:1:N}"
  shift $N || set --
done

РЕДАКТИРОВАТЬ #2 :Параллелизм и использование памяти

После прочтения этого поста здесь:https://unix.stackexchange.com/a/321765/439686мне пришло в голову, что мои предыдущие две версии могут столкнуться с серьезными проблемами, если мы имеем дело с огромным количеством каталогов. Помимо серьезной нагрузки на память, они также неэффективны, так как ожидают, что findнайдет весь список каталогов, прежде чем мы даже запустим первую команду zip. Было бы гораздо лучше, если бы мы запускали вещи в парралелле --через пайпы --, и тогда не будет иметь значения, сколько там файлов. Это оставляет нам единственно возможное правильное решение --сделать это с помощью find... -print0 | xargs -0 command.Почему xargs? Потому что он может запускать команды с N аргументами за раз, вместо того, чтобы ждать весь список, а также потому, что xargsможет работать с нулевыми -строками с разделителями, которые -print0будут ему передавать по конвейеру. И мы обязательно должны использовать ноль в качестве разделителя, потому что имена файлов могут содержать любые другие символы, включая символы новой строки. В качестве дополнительного бонуса с помощью xargsмы можем даже запускать несколько процессов одновременно, чтобы лучше использовать многоядерную систему. Итак, вот он:

#!/bin/bash
rootdir=${1:-/your/parent/directory}
N=10 # group size
mktemp --version >/dev/null || exit 1
stamp=$(date +%Y%m%d%H%M)
cores=$(nproc) || cores=1
export rootdir N stamp cores

find "$rootdir" -type d -mindepth 1 -maxdepth 1 -print0 \
  | xargs -r0  --max-args=$N  --max-procs=$cores  bash -c '
  zip -r "$(mktemp -u -p "$rootdir" group.$stamp.XXXXXX.zip)" "$@" ' ""

Результат:

group.202103140805.7H1Don.zip
group.202103140805.akqmgX.zip
group.202103140805.fzBsUZ.zip
group.202103140805.iTfmj8.zip
...
1
18.03.2021, 22:25

Вы можете вызывать zip -r zipfile files_or_dirsнесколько раз для одного и того же zipfileи делать это в цикле.

Приведенный ниже сценарий рекурсивно добавит 10 подкаталогов текущего каталога (со всеми файлами и подкаталогами в них )в ZIP-файл, а затем переключится на следующий ZIP-файл. Он будет игнорировать файлы в текущем каталоге. Размер ZIP-файлов зависит от данных в подкаталогах. Последний ZIP-файл может содержать менее 10 подкаталогов.

Поскольку вопрос относится к ответу, который использует for i in */; do zip -r "${i%/}.zip" "$i"; doneи указывает единственное дополнительное требование, которое, например. 10 подкаталогов должны храниться в ZIP-файле вместо одного ZIP-файла на подкаталог, я предполагаю, что не требуется архивировать каталоги, начинающиеся с точки.

#!/bin/bash
zipnum=0
i=0
for dir in./*/
do
    zip -r archive$zipnum.zip "$dir" # recursively add this dir to the archive
    ((i++))            # count directories
    if [[ i -ge 10 ]]  # maximum number of directories per ZIP file
    then
        i=0            # reset directory counter
        ((zipnum++))   # next ZIP file number
    fi
done

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

Поскольку скрипт считает 0, 1,..., 9, 10, 11,..., вы можете получить ZIP-файлы с разным количеством цифр, что может привести к неожиданной (лексикографической )сортировке, например

archive0.zip
archive1.zip
archive10.zip
archive11.zip
archive2.zip
archive3.zip
...
1
18.03.2021, 22:25

Теги

Похожие вопросы