Aqui está uma solução relativamente simples que executa find
apenas uma vez, armazena sua saída em um arquivo temporário e, em seguida, divide e agrupa os resultados para as duas extensões.
tmp=$(mktemp)
find . -name '*.ext1' -o -name '*.ext2' | sort >"$tmp"
comm -12 <(<tmp sed -n 's!/[^/]*\.ext1$!!p' | sort) \
<(<tmp sed -n 's!/[^/]*\.ext2$!!p' | sort)
rm "$tmp"
Outro método é executar find
para iterar nos diretórios e usa um programa auxiliar para verificar se um padrão tem correspondências. Note que a verificação de existência funciona neste caso, mas você precisa de algo mais complicado se o padrão de pesquisa não corresponder a si mesmo e for um possível nome de arquivo.
find . -type d -exec sh -c '{ set "$0"/*.ext1; [ -e "$1" ]; } &&
{ set "$0"/*.ext2; [ -e "$1" ]; }' {} \;
Aqui está uma solução zsh que opera como este último comando:
echo **/*(/e\''set -- $REPLY/*.ext1(N[1]) $REPLY/*.ext2(N[1]); ((#==2))'\')
Aqui está outra solução zsh que procura *.ext1
e seleciona apenas os diretórios que também têm *.ext2
:
echo ./**/*.ext1(e\''REPLY=${REPLY:h}; set -- $REPLY/*.ext2(N); ((#))'\')
Aqui está uma solução Perl parcial; Devido às vicissitudes do globbing de Perl, ele não funcionará se os nomes dos diretórios contiverem espaços (existem maneiras de corrigir isso, mas não consigo encontrar um que seja remotamente elegante).
perl -l -MFile::Find -e \
'find {no_chdir => 1,
wanted => sub {<$_/*.ext1> and <$_/*.ext2> and print}}, "."'