O script a seguir criará pacotes compactados de arquivos dentro do diretório especificado. Você invoca como:
script.sh directorypath
Ele usa um algoritmo simples / ingênuo (assim como o que você descreveu):
- Conte todos os arquivos.
- Comece a ler todos os arquivos de forma recursiva.
- Obtenha o tamanho, a entrada ls e a soma de verificação (SHA1) de cada arquivo. (Armazene a entrada ls no manifest.txt e a soma de verificação no checksum.txt).
- Se o tamanho acabou de passar do limite, use a lista manifest.txt para criar um tar compactado (que também inclui os arquivos manifest e checksum).
- Crie um diretório temporário e descompacte apenas o tar criado.
- Calcule novas somas de verificação dos arquivos extraídos.
- Compare com as somas de verificação armazenadas.
- Se pelo menos uma soma de verificação for diferente, saia com um erro.
- Caso contrário, verifique se a opção de exclusão está ativada. Em caso positivo, remova os arquivos de origem.
- Repetir até não haver mais arquivos.
Sua saída é como:
Reading files...
15898 849 ../out/f068715p.jpg
Creating package (pack18.tar.gz) with 849 files, using 100078420 bytes...
tar: Removing leading '../' from member names
Preparing to verify package...
Creating new checksums...
Comparing checksums...
Package verification OK.
Deleting temporary verification directory...
Reading files...
16731 833 ../out/f069111c.jpg
Creating package (pack19.tar.gz) with 833 files, using 100004735 bytes...
tar: Removing leading '../' from member names
Preparing to verify package...
Creating new checksums...
Comparing checksums...
Package verification OK.
Deleting temporary verification directory...
Reading files...
Os arquivos do pacote são criados no diretório atual.
Um aviso:
- o diretório atual e o diretório de origem não devem ser pai / filho ou filho / pai, ele não foi testado dessa maneira.
Este é o script (O PACKSIZELIMIT é o número de bytes, se DELETESOURCE for 1, então ele excluirá arquivos de origem [bem, você também deve remover o # simbol antes da linha "rm -f"]):
#!/bin/bash
PACKSIZELIMIT=100000000
PACKPREFFIX="pack"
#PACKSUFFIX=$(date +"_%Y%m%d_%H%M")
PACKSUFFIX=""
DELETESOURCE=0
LISTFILE="packbatchlist.txt"
MANIFESTFILE="manifest.txt"
CHECKSUMFILE="checksums.txt"
VERIFYFILE="verifysums.txt"
if [ -d "$1" ]; then
PACKCOUNTER=0
PACKSIZE=0
FILECOUNTER=0
ALLFILECOUNTER=0
cat /dev/null > $LISTFILE
cat /dev/null > $MANIFESTFILE
cat /dev/null > $CHECKSUMFILE
cat /dev/null > $VERIFYFILE
echo "Reading files..."
TOTALFILES=$(find "$1" -type f | wc -l)
echo "There are $TOTALFILES files to process..."
find "$1" -type f | while read SOURCEFILE ; do
let "FILECOUNTER+=1"
let "ALLFILECOUNTER+=1"
echo -ne "\r$ALLFILECOUNTER $FILECOUNTER $SOURCEFILE\e[K"
THISFILESIZE=$(stat -c %s "$SOURCEFILE")
let "PACKSIZE+=$THISFILESIZE"
echo $SOURCEFILE >> $LISTFILE
ls -l $SOURCEFILE >> $MANIFESTFILE
sha1sum $SOURCEFILE >> $CHECKSUMFILE
if [ $PACKSIZE -gt $PACKSIZELIMIT -o $ALLFILECOUNTER -eq $TOTALFILES ]; then
echo
echo $MANIFESTFILE >> $LISTFILE
echo $CHECKSUMFILE >> $LISTFILE
PACKFILENAME="$PACKPREFFIX$PACKCOUNTER$PACKSUFFIX.tar.gz"
echo "Creating package ($PACKFILENAME) with $FILECOUNTER files, using $PACKSIZE bytes..."
tar -cf - -T $LISTFILE | gzip -c > $PACKFILENAME
echo "Preparing to verify package..."
TEMPCHECKDIR=$(mktemp -d)
tar xzf $PACKFILENAME -C $TEMPCHECKDIR
if [ -r "$TEMPCHECKDIR/$CHECKSUMFILE" ] ; then
cut -d " " -f 1 $TEMPCHECKDIR/$CHECKSUMFILE > $VERIFYFILE
sort $VERIFYFILE > $TEMPCHECKDIR/$CHECKSUMFILE
echo "Creating new checksums..."
cat /dev/null > $VERIFYFILE
find "$TEMPCHECKDIR" -type f | while read CHECKEDFILE ; do
CHECKEDFILESHORT=$(basename $CHECKEDFILE)
if [ "$CHECKEDFILESHORT" != "$MANIFESTFILE" -a "$CHECKEDFILESHORT" != "$CHECKSUMFILE" ] ; then
sha1sum $CHECKEDFILE | cut -d " " -f 1 >> $VERIFYFILE
fi
done
sort $VERIFYFILE -o $VERIFYFILE
echo "Comparing checksums..."
DIFFFILES=$(comm --nocheck-order -3 $TEMPCHECKDIR/$CHECKSUMFILE $VERIFYFILE | wc -l)
if [ $DIFFFILES -gt 0 ] ; then
echo "ERROR: Package failed verification!"
exit 2
else
echo "Package verification OK."
echo "Deleting temporary verification directory..."
find "$TEMPCHECKDIR" -delete
if [ "$DELETESOURCE" == "1" ] ; then
echo "Deleting source files..."
cat $LISTFILE | while read FILE2DEL ; do
echo -ne "\rDeleting $FILE2DEL ... \e[K"
#rm -f $FILE2DEL
done
echo -e "\rFiles deleted.\e[K"
fi
fi
else
echo "ERROR: Cannot find checksum file from package!"
exit 1
fi
let "PACKCOUNTER+=1"
PACKSIZE=0
FILECOUNTER=0
cat /dev/null > $LISTFILE
cat /dev/null > $MANIFESTFILE
cat /dev/null > $CHECKSUMFILE
cat /dev/null > $VERIFYFILE
echo "Reading files..."
fi
done
else
echo
echo "Missing source directory"
echo
fi
rm -f $LISTFILE
rm -f $MANIFESTFILE
rm -f $CHECKSUMFILE
rm -f $VERIFYFILE