Isso parece atingir sua meta
#!/bin/bash
for DIR in {a..z}
do
GOOD=$(find ${DIR}[0-9] -type d -print -prune 2>/dev/null | tail -1)
if [[ "$GOOD" ]]; then
echo $GOOD
fi
done
Exemplo de uso:
$ mkdir a1 b1 c1 c2 c3 d1
$ ./a.sh
a1
b1
c3
d1
$
Eu tenho um diretório organizado em subdiretórios da maneira de:
a1
b1
c1
c2
c3
d1
Estou tentando executar um loop que só é executado no subdiretório mais recente de uma determinada letra, ou seja, seria executado em a1
, b1
, c3
e d1
, mas ignore c1
e c2
. Meus esforços até agora giraram em torno de tentar comparar diretamente os valores numéricos dos nomes dos subdiretórios, mas isso não funcionou muito bem. Eu sou novo no bash, então peço desculpas se essa for uma correção simples que estou perdendo.
Isso parece atingir sua meta
#!/bin/bash
for DIR in {a..z}
do
GOOD=$(find ${DIR}[0-9] -type d -print -prune 2>/dev/null | tail -1)
if [[ "$GOOD" ]]; then
echo $GOOD
fi
done
Exemplo de uso:
$ mkdir a1 b1 c1 c2 c3 d1
$ ./a.sh
a1
b1
c3
d1
$
Eu tenho um pequeno canal complicado para fazer o seu trabalho:
#!/bin/bash
find . -maxdepth 1 -type d |
sed -e '/\.$/d' -e '/\.\.$/d' -e 's/\.\/\(.\)\(.\)/ /' |
sort -k1.1 -k2.1n |
awk 'BEGIN {last=""}
{
if (last == "") {
last = $1; number = $2
} else if ($1 != last) {
printf "%s%s\n", last, number;
last = $1; number = $2
} else {
number = $2
}
}
END { printf "%s%s\n", last, number }
'
Você provavelmente terá que alterar os argumentos para find
para obter exatamente o que deseja.
Uma forma de agir no último de uma série é percorrer todos os elementos, lembrando-se do item anterior. Se você detectar que uma nova série está começando, atue no item anterior lembrado. Código não testado. Presumo que você esteja interessado apenas em diretórios cujo primeiro caractere não é um ponto e cujo último caractere é um dígito.
act_on () {
…
}
previous_prefix=0
previous_name=
for x in *[0-9]/; do
x=${x%/}
digits=${x##*[!0-9]}
prefix=${x%"$digits"}
if [ "$prefix" != "$previous_prefix" ] && [ "$previous_prefix" != "0" ]; then
# New prefix, so act on the previous element
act_on "$previous_name"
fi
previous_prefix=$prefix
previous_name=$x
done
act_on "$previous_name"
Tenha em atenção que foo9
é classificado após foo10
. Em zsh, use *[0-9](/on)
para usar a classificação numérica, em que 9
é classificado antes de 10
. Se você não estiver usando o zsh, será necessária uma abordagem diferente. Uma maneira é agir apenas no primeiro item da série, mas em vez de agir sobre o item encontrado, use seu prefixo e determine o último elemento da série numérica.
act_on () {
…
}
previous_prefix=0
previous_name=
for x in *[0-9]/; do
x=${x%/}
digits=${x##*[!0-9]}
prefix=${x%"$digits"}
if [ "$prefix" != "$previous_prefix" ]; then
suffixes=
for y in "$prefix"*; do
suffixes="$suffixes
${y#"$prefix"}"
done
last_suffix=$(echo "$suffixes" | sort -n | tail -n 1)
act_on "$prefix$last_suffix"
fi
previous_prefix=$prefix
previous_name=$x
done
Se os seus nomes de diretório são tão simples quanto você mostra (pelo menos, se não contiver espaço em branco ou outra estranheza), você poderia fazer:
for d in $(ls | sort -r | rev | uniq -s1 | rev); do echo "$d"; done
Altere o echo "$4d"
para o que seu loop deve estar fazendo. No entanto, isso falhará se os nomes dos seus diretórios não forem exatamente como você os mostra, pois é vulnerável a todas as armadilhas da análise de ls. Ele trabalha primeiro listando os diretórios, classificando-os em ordem reversa, invertendo-os (assim a1
se torna 1a
), mantendo apenas linhas exclusivas, mas ignorando o primeiro caractere ( uniq -s1
) e revertendo-as para obter o original nome de volta.
Tags bash