com zsh
:
has() ()(($#)) $REPLY/$~1(N)
ls -- **/*(/e{has Makefile}e{has \*.c})
has
lá é definido como uma função que verifica se o glob dado como argumento resolve qualquer arquivo no diretório $REPLY
. Usamos essa função no qualificador e
glob para decidir se os diretórios são selecionados. Alguns dos recursos do zsh lá:
-
() {compound-command} arguments
: função anônima. Aqui o código dessa função é(($#))
, que retorna verdadeiro se o número de argumentos for diferente de zero -
$~1
:zsh
não divide + glob por padrão após a expansão do parâmetro. Você precisa solicitá-lo explicitamente$~1
é para solicitar a parte glob sobre a expansão de$1
, que é para$1
para ser tomada como um padrão. -
(N)
: qualificador glob que ativa nullglob para aquele glob, que diz ao glob para expandir para nada se ele não corresponder a nenhum arquivo. -
**/
: qualquer nível de subdiretórios -
(/e...)
: outro qualificador de glob, em que/
corresponde apenas a arquivos do tipo diretório ee{code}
que corresponde a arquivos para os quais o código é verdadeiro ( com o arquivo armazenado em$REPLY
).
Adicione alguns qualificadores D
glob se você quiser olhar para diretórios ocultos e considerar arquivos c
ocultos:
printf '%s\n' **/*(D/e{has Makefile}e{'has "*.c(#qD)"'})
Com ferramentas GNU:
LC_ALL=C find . \( -name '*.c' -o -name Makefile \) -print0 |
LC_ALL=C awk -v RS='LC_ALL=C find . -name '.?*' -prune -o \( -name '*.c' -o -name Makefile \) -print0
' -v ORS='has() ()(($#)) $REPLY/$~1(N)
ls -- **/*(/e{has Makefile}e{has \*.c})
' '
{dirname = $0; sub("/[^/]*$", "", dirname)}
/\.c$/ {hasc[dirname]; next}
{hasMakefile[dirname]}
END {for (dir in hasc) if (dir in hasMakefile) print dir}' |
xargs -r0 ls
Se você não quiser descer em diretórios ocultos e não considerar arquivos C ocultos, altere o comando find
para:
printf '%s\n' **/*(D/e{has Makefile}e{'has "*.c(#qD)"'})
Esses fornecerão o caminho e o conteúdo dos diretórios correspondentes, mas se houver apenas um diretório correspondente, ls
não exibirá seu caminho. Você pode substituir ls --
por printf '%s\n'
se desejar apenas os caminhos dos diretórios correspondentes.