find . -type f -name '*f*' | sed -r 's|/[^/]+$||' |sort |uniq
O texto acima localiza todos os arquivos abaixo do diretório atual ( .
) que são arquivos regulares ( -type f
) e que têm f
algum lugar em seu nome ( -name '*f*'
). Em seguida, sed
remove o nome do arquivo, deixando apenas o nome do diretório. Em seguida, a lista de diretórios é classificada ( sort
) e as duplicatas removidas ( uniq
).
O sed
comando consiste em um único substituto. Ele procura correspondências para a expressão regular /[^/]+$
e substitui qualquer coisa que corresponda a isso por nada. O cifrão significa o fim da linha. [^/]+'
significa um ou mais caracteres que não são barras. Assim, /[^/]+$
significa todos os caracteres da barra final até o final da linha. Em outras palavras, isso corresponde ao nome do arquivo no final do caminho completo. Portanto, o comando sed remove o nome do arquivo, deixando inalterado o nome do diretório em que o arquivo estava.
Simplificações
Muitos sort
comandos modernos suportam uma -u
bandeira que torna uniq
desnecessária. Para GNU sed:
find . -type f -name '*f*' | sed -r 's|/[^/]+$||' |sort -u
E, para o MacOS sed:
find . -type f -name '*f*' | sed -E 's|/[^/]+$||' |sort -u
Além disso, se o seu find
comando o suportar, é possível find
imprimir diretamente os nomes dos diretórios. Isso evita a necessidade de sed
:
find . -type f -name '*f*' -printf '%h\n' | sort -u
Versão mais robusta (requer ferramentas GNU)
As versões acima serão confundidas com nomes de arquivos que incluem novas linhas. Uma solução mais robusta é fazer a classificação em cadeias terminadas em NUL:
find . -type f -name '*f*' -printf '%h\0' | sort -zu | sed -z 's/$/\n/'
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
-E
no MacOS.Por que não tentar isso:
fonte
find
são na verdade bastante esparsas - o-printf
operador não está especificado. Isso não funciona com o BSDfind
. Portanto, não é "totalmente compatível com POSIX". (Emborasort -u
esteja em POSIX .)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
ouawk
é, 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
Exclua alguns dos
*f*
arquivos dedir1/*
:Abordagem # 1 - Analisando via Strings
Aqui nós estamos indo para usar as seguintes ferramentas,
find
,grep
, esort
.Abordagem # 2 - Análise usando arquivos
A mesma cadeia de ferramentas de antes, exceto que desta vez usaremos em
dirname
vez degrep
.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
grep
Portanto, é sempre melhor lidar com as cordas, se possível.
Métodos alternativos de análise de string
grep & PCRE
sed
awk
fonte
Aqui está um que eu acho útil:
fonte
Esta resposta é descaradamente baseada na resposta slm. Foi uma abordagem interessante, mas tem uma limitação se os nomes de arquivos e / ou diretórios tiverem caracteres especiais (espaço, semi-coluna ...). Um bom hábito é usar
find /somewhere -print0 | xargs -0 someprogam
.Dados de amostra
Para os exemplos abaixo, usaremos os seguintes dados
Exclua alguns dos
*f*
arquivos dedir1/*/
:Abordagem # 1 - Análise usando arquivos
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! Além disso, substitua oecho
comando que você deseja usar.fonte
Com
zsh
:fonte