Eu usei com sucesso o seguinte:
zip -r [target_zip] [folder_to_zip] 2>&1 |
pv -lep -s $(ls -Rl1 [folder_to_zip] | egrep -c '^[-/]') > /dev/null
E isso é explicado abaixo:
zip -r [target_zip] [folder_to_zip] 2>&1 |
zip recursivamente no arquivo [target_zip] o [folder_to_zip] redirecionando o stderr para stdout. Note que stderr conterá uma linha para cada arquivo e diretório sendo processado.
pv -lep -s $(ls -Ral1 [folder_to_zip] | egrep -c '^[-/]') > /dev/null
canalize para pv as linhas com os nomes dos arquivos conforme eles estão sendo emitidos pelo zip. pv é operado em modo de linha (contando o progresso baseado em linhas e tamanho também está em número de linhas para esperar - veja página de manual de PV - l opção ).
O tamanho total das linhas a serem esperadas é reunido listando recursivamente (ls) o [folder_to_zip] e contando as linhas que começam com '-' ou 'd' ou seja, todos os arquivos e diretórios (lembre-se diretórios são listados a partir com '/') .
O texto acima fornece uma porcentagem exata de conclusão, pois o 100% é atingido quando todos os arquivos e diretórios são processados.
O problema com a resposta do pedroapero é que o progresso é calculado no número de bytes processados (compactados) sobre o número total de bytes a serem processados (não compactados). Como resultado, o processo será concluído em torno de 30% (dependendo da taxa de compactação).