find . -type f -name '*f*' | sed -r 's|/[^/]+$||' |sort |uniq
Os itens acima encontram todos os arquivos abaixo do diretório atual ( .
) que são arquivos regulares ( -type f
) e têm f
em 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 são removidas ( uniq
).
O comando sed
consiste em um único substituto. Ele procura por correspondências com a expressão regular /[^/]+$
e substitui qualquer coisa que corresponda a isso com nada. O cifrão significa o fim da linha. [^/]+'
significa um ou mais caracteres que não são barras. Portanto, /[^/]+$
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. Assim, o comando sed remove o nome do arquivo, deixando inalterado o nome do diretório em que o arquivo estava.
Simplificações
Muitos comandos sort
modernos suportam um sinal -u
, o que torna uniq
desnecessária. Para o 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 comando find
for compatível, é possível ter find
imprimir os nomes dos diretórios diretamente. 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 por nomes de arquivos que incluem novas linhas. Uma solução mais robusta é fazer a classificação em strings terminadas em NUL:
find . -type f -name '*f*' -printf '%hfind . -type f -name '*f*' | sed -r 's|/[^/]+$||' |sort |uniq
' | sort -zu | sed -z 's/$/\n/'