Crie um arquivo zip com base no número de arquivos

Crie um arquivo zip com base no número de arquivos

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 arquivo
  • COMMAND- $FILEé interpretado splitcomo 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, splitnã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

informação relacionada