Aqui está minha sugestão, removendo variáveis de uma letra e mudando a localização do arquivo para fins de consistência:
#!/system/bin/sh -xv
cd "$PWD/../WorkingDir"
compress() {
# Detect only known dir names, convert slash to underscore
local arch="$(echo $1 | sed -rne '/320\/(light|dark)/s@/@_@gp')"
# Set a default value to the variable
: ${arch:=file}
# Only create a ZIP archive if not present in the parent directory
# Note $PWD is evaluated *before* cd
[ -f "${arch}.zip" ] || ( cd -- $1 && zip -0rq "${PWD}/${arch}.zip ." )
}
for dir in */*/; do
compress $dir
done
Basta alterar a linha sed
para adicionar o que chamei de "nomes de diretório conhecidos".
EDITAR : Adicionando algumas explicações, conforme a solicitação do OP.
O script verifica as condições antes de compactar os diretórios sempre que um novo diretório é localizado pelo loop for
. Variáveis também foram eliminadas. Vamos dissecar o código.
O loop principal
cd "$PWD/../WorkingDir"
for dir in */*/; do # Ensures to select only directories
compress $dir # compress runs some checks prior to compressing
done
Na verdade, não há muito mais a dizer sobre isso.
A rotina compress
local arch="$(echo $1 | sed -rne '/320\/(light|dark)/s@/@_@gp')"
$1
é o argumento passado para compressed
, ou seja, o diretório para verificar e compactar. O que sed
faz primeiro ( '/320\/(light|dark)/'
) é verificar se o caminho está no formato
320/light
320/dark
e retorna o caminho com a barra convertida em um sublinhado: 's@/@_@g'
. Usando o sinal de arroba como um separador para facilitar a leitura, para evitar escapar da barra. Outras notações válidas são 's:/:_:g'
ou 's#/#_#g'
ou o clássico 's/\//_/g'
. Observe como a barra para transformar é escapada com um anti-slash. Eu acho a última forma menos legível embora.
O p
à direita funciona em conjunto com sed -n
; a última opção neste caso em particular significa « não ecoa nada a menos que seja informado por p
sempre que uma correspondência (ou seja, nas barras envolventes) for encontrada ». Portanto arch
conterá um caminho com a barra transformada em um sublinhado se e somente se a expressão regular 320\/(light|dark)
for encontrada no caminho. Caso contrário, não fará eco, tornando arch
uma variável em branco.
A opção -r
é uma maneira conveniente de informar sed
para usar expressões regulares canônicas, mais legível. Caso contrário, você precisaria escapar dos parênteses e dos caracteres do pipe. Eu acho '/320\/(light|dark)/s@/@_@gp'
mais legível que '/320\/\(light\|dark\)/s@/@_@gp'
ou '/320\/\(light\|dark\)/s/\//_/gp'
.
: ${arch:=file}
Esta linha define arch
para seu valor padrão "file" se estiver em branco. A construção estranha é necessária porque ${arch:=file}
sozinho dispara um erro de sintaxe. Os dois pontos dizem ao shell para não fazer nada ( :
), mas atribuem arch
um valor, se estiver em branco.
[ -f "${arch}.zip" ] || ( cd -- $1 && zip -0rq "${PWD}/${arch}.zip ." )
Aqui eu usei -f
em vez de -e
porque o primeiro também verifica arquivos com comprimento zero. O teste só terá sucesso se existir um arquivo ZIP e com comprimento diferente de zero.
Se não houver arquivo no diretório pai (ou no diretório atual ) ou se o tamanho for nulo, o script gerará um sub-shell que será alterado para o diretório passado como argumento para compress
e fecha seu conteúdo. Note que as variáveis $1
e $PWD
são avaliadas antes o sub-shell executa suas instruções, ou seja, $PWD
é igual ao diretório pai $Z
em sua versão inicial.
Expandindo o filtro
Você pode agir com base em sed
da seguinte maneira:
sed -rne '/320\/(light|dark|play)/s@/@_@gp'
para verificar nomes de diretório como
320/light
320/dark
320/play
Você também pode considerar /(320|480|540)\/(light|dark|play)/
, o que lhe dá 9 combinações, ou um formulário mais genérico /[0-9]+\/(light|dark|play)/
(qualquer número seguido por uma barra e um de " luz ", " dark "e" play ") ou mesmo /[0-9]+\/\w+/
(qualquer número seguido por uma barra e uma palavra aka [A-Za-z0-9_]+
). Tudo depende de quão rigoroso ou amplo você deseja que o filtro seja.