![Crie um arquivo zip com base no número de arquivos](https://rvso.com/image/89166/Crie%20um%20arquivo%20zip%20com%20base%20no%20n%C3%BAmero%20de%20arquivos.png)
Sun OS 5.8
Estrutura de diretório
/TESTE/CHM
CHM
A
file1.txt
file2.txt
B
file3.txt
C
file4.txt
file5.txt
file6.txt
Se o diretório pai CHM tiver menos de 8 arquivos/subdiretórios, feche-o normalmente. Se o diretório pai CHM tiver 8 ou mais arquivos/subdiretórios, crie um arquivo zip para cada 5 arquivos. Isto é apenas para teste. Na produção serão 10.000 arquivos, não 5. O diretório pai CHM pode ter de 0 a n subdiretórios.
#!/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)
A outra parte da segunda instrução if está falhando e não sei por quê. Estou procurando criar:
CHM.zip master
CHM.001.zip
CHM.002.zip
CHM.003.zip
Assim posso descompactar na mesma ordem em um servidor remoto.
Responder1
Não tenho certeza se segui completamente suas regras, mas pode ser mais fácil usar utilitários padrão (e simplificar as regras sobre o que e quando criar):
find . -type f | split -d -a3 -l $num --filter='zip -@ $FILE.zip' - "$pfx".
find
é bastante óbvio, ajuste as opções ao seu gosto. Você pode ordenar a lista antes de passar sua saída para split
.
split
:
- d
- use numeração em vez de sufixos alfabéticos-a3
- comprimento do sufixo (a numeração) 3 casas (dígitos neste caso)-l
- número de linhas após as quais aumentar o contador--filter=COMMAND
- passar linhas para um comando em vez de escrever em um arquivoCOMMAND
-$FILE
é interpretadosplit
como um nome de arquivo que normalmente usaria para escrita, o que significa que deve estar entre aspas simples (ou barra invertida para evitar a interpretação pelo shell que executa a linha de comando acima)-
- requer explicitamente a análise da entrada padrão"$pfx".
seu prefixo preferido. O ponto é intencional,split
não o acrescenta automaticamente.
Responder2
Eu tenho a solução que funciona no Sun Solaris. Isso compactará 10.000 arquivos por cada zip multiparte e enviará o zip mestre para o servidor remoto.
#!/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