![Создать zip-архив на основе количества файлов](https://rvso.com/image/89166/%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D1%82%D1%8C%20zip-%D0%B0%D1%80%D1%85%D0%B8%D0%B2%20%D0%BD%D0%B0%20%D0%BE%D1%81%D0%BD%D0%BE%D0%B2%D0%B5%20%D0%BA%D0%BE%D0%BB%D0%B8%D1%87%D0%B5%D1%81%D1%82%D0%B2%D0%B0%20%D1%84%D0%B0%D0%B9%D0%BB%D0%BE%D0%B2.png)
SunOS 5.8
Структура каталога
/ТЕСТ/ЧМ
CHM
A
file1.txt
file2.txt
B
file3.txt
C
file4.txt
file5.txt
file6.txt
Если родительский каталог CHM содержит менее 8 файлов/подкаталогов, заархивируйте его обычным способом. Если родительский каталог CHM содержит 8 или более файлов/подкаталогов, создайте zip-архив для каждых 5 файлов. Это только для тестирования. В производстве это будет 10000 файлов, а не 5. Родительский каталог CHM может содержать от 0 до n подкаталогов.
#!/bin/bash
set -e
cd $subdir/
# vars
num=8 # set 10000 in production
for dir in $subdir
do
dir=${dir%*/}
# testing code only
if [[ ${dir##*/} = "CHM" ]]
then
numfile=$(ls * | wc -l)
fi
if [ "$numfile" -lt "$num" ]
then
zip -r -6 ${dir##*/}.zip .
else
ls * > files
split -l 5 - files < files
for i in files[a-z][a-z]; do
zip -6 "$i.zip" -@ < "$i"
done
fi
# end test
done
exit
zip warning: name not matched: A:
zip warning: name not matched: file1.txt
zip warning: name not matched: file2.txt
zip warning: name not matched: B:
zip error: Nothing to do! (filesaa.zip)
Часть else второго оператора if не работает, и я не уверен, почему. Я пытаюсь создать:
CHM.zip master
CHM.001.zip
CHM.002.zip
CHM.003.zip
Поэтому я могу распаковать архив в том же порядке на удаленном сервере.
решение1
Я не совсем уверен, что полностью следовал вашим правилам, но, возможно, будет проще использовать стандартные утилиты (и упростить правила того, что и когда создавать):
find . -type f | split -d -a3 -l $num --filter='zip -@ $FILE.zip' - "$pfx".
find
довольно очевидно, настройте параметры по своему вкусу. Вы можете захотеть отсортировать список перед передачей его вывода в split
.
split
:
- d
- используйте нумерацию вместо алфавитных суффиксов-a3
- длина суффикса (нумерация) 3 знака (в данном случае цифры)-l
- количество строк, после которого нужно увеличить счетчик--filter=COMMAND
- передавать строки команде вместо записи в файлCOMMAND
-$FILE
интерпретируетсяsplit
как имя файла, которое обычно используется для записи, что означает, что оно должно быть заключено в одинарные кавычки (или в обратную косую черту, чтобы предотвратить интерпретацию оболочкой, выполняющей указанную выше командную строку)-
- явно требовать разбор стандартного ввода"$pfx".
ваш предпочтительный префикс. Точка намеренная,split
не добавляется автоматически.
решение2
У меня есть решение, которое работает на Sun Solaris. Оно заархивирует 10000 файлов в каждом многокомпонентном zip-архиве и отправит главный zip-архив на удаленный сервер.
#!/usr/bin/env bash
#
#------------------------------------------------------------
#-- Zip up content files based on $1 parameter
#------------------------------------------------------------
function zip_files {
SRC="/ads/data02/CTS/Data/$1"
#-- destination folder
DST="/ads/acct/oracle/CTS"
#-- amount of files that should go in each zip file
FILES_PER_ZIP=10000
#-----------------------------------------------------------
FILES="/tmp/multizip.$$"
ZIP_PREFIX=$(basename $SRC)
#-- generate the list of the files to zip
find $SRC > $FILES
#-- zip the files
NUM=0
ZIP_NUM=1
printf -v ZIPFILE "$DST/$ZIP_PREFIX%03d" $ZIP_NUM
while read -r line; do
echo $line | sed -e 's/.*/"&"/' | xargs zip -6 $ZIPFILE
((NUM++))
if [ $NUM -eq $FILES_PER_ZIP ]; then
NUM=0
((ZIP_NUM++))
printf -v ZIPFILE "$ZIP_PREFIX%03d" $ZIP_NUM
fi
done < $FILES
#-- generate master zip file
/usr/bin/ls $DST/${ZIP_PREFIX}*.zip | xargs zip $DST/$ZIP_PREFIX
#-- perform cleanup
function finish {
/usr/bin/rm $FILES
/usr/bin/rm /ads/acct/oracle/CTS/${ZIP_PREFIX}[0-9][0-9][0-9].zip
}
trap finish EXIT
}
#------------------------------------------------------------
#-- Main processing
#------------------------------------------------------------
for dir in /ads/data02/CTS/Data/*/
do
d=$(basename $dir)
zip_files $d
scp "/ads/acct/oracle/CTS/${d}.zip" [email protected]:/var/www/html/CTS/Content/A/TMP
/usr/bin/rm -f "/ads/acct/oracle/CTS/${d}.zip"
done
exit