Existem essencialmente 2 métodos que você pode usar para fazer isso. Um analisará a string enquanto o outro operará em cada arquivo. Analisando a corda usar uma ferramenta como grep
, sed
ou awk
é, obviamente, vai ser mais rápido, mas aqui está um exemplo mostrando tanto, bem como como você pode "perfil" dos 2 métodos.
Dados de amostra
Para os exemplos abaixo, usaremos os seguintes dados
$ touch dir{1..3}/dir{100..112}/file{1..5}
$ touch dir{1..3}/dir{100..112}/nile{1..5}
$ touch dir{1..3}/dir{100..112}/knife{1..5}
Exclua alguns dos *f*
arquivos de dir1/*
:
$ rm dir1/dir10{0..2}/*f*
Abordagem # 1 - Analisando via Strings
Aqui nós estamos indo para usar as seguintes ferramentas, find
, grep
, e sort
.
$ find . -type f -name '*f*' | grep -o "\(.*\)/" | sort -u | head -5
./dir1/dir103/
./dir1/dir104/
./dir1/dir105/
./dir1/dir106/
./dir1/dir107/
Abordagem # 2 - Análise usando arquivos
A mesma cadeia de ferramentas de antes, exceto que desta vez usaremos em dirname
vez de grep
.
$ find . -type f -name '*f*' -exec dirname {} \; | sort -u | head -5
./dir1/dir103
./dir1/dir104
./dir1/dir105
./dir1/dir106
./dir1/dir107
NOTA: Os exemplos acima estão usando head -5
apenas para limitar a quantidade de saída com a qual estamos lidando nesses exemplos. Eles normalmente seriam removidos para obter sua lista completa!
Comparando os resultados
Podemos usar time
para dar uma olhada nas 2 abordagens.
dirname
real 0m0.372s
user 0m0.028s
sys 0m0.106s
grep
real 0m0.012s
user 0m0.009s
sys 0m0.007s
Portanto, é sempre melhor lidar com as cordas, se possível.
Métodos alternativos de análise de string
grep & PCRE
$ find . -type f -name '*f*' | grep -oP '^.*(?=/)' | sort -u
sed
$ find . -type f -name '*f*' | sed 's#/[^/]*$##' | sort -u
awk
$ find . -type f -name '*f*' | awk -F'/[^/]*$' '{print $1}' | sort -u
uniq
na mistura ajuda muito removendo as linhas repetidas que já estão próximas umas das outras.find . -type f -name '*f*' -printf '%h\0' | uniq -z | sort -zu | tr '\0' '\n'
. Ou, se suas ferramentas forem um pouco mais antigas, o uniq pode não ter a opção -z.find . -type f -name '*f*' -printf '%h\n' | uniq | sort -u