Como procuro pastas que tenham arquivos .c junto com o Makefile? Eu quero os nomes ou conteúdos das pastas

2

Eu tenho algumas pastas que possuem ambos .c e Makefile. Eu preciso saber quais pastas têm isso. Qual comando eu digito no linux para encontrar essas pastas?

    
por user3800888 27.06.2017 / 16:51

3 respostas

2

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 e e{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.

    
por 27.06.2017 / 17:35
1

Não é uma resposta séria, mas problemas como esse às vezes fazem com que desejemos o SQL-in-shell, ou talvez o contrário, algo como:

 find . -type f |
 awk -F/ -vOFS=/ -vq=\' 'BEGIN{print "create table temp (dir varchar, f varchar);"}
      {f=$(NF--); print "insert into temp values(" q $0 q "," q f q ");" }
      END{print "select dir from temp group by dir ";
           print "having sum(when f like "q"%.c"q" then 1 else 0 end)>0 ";
           print "and sum(when f="q"Makefile"q" then 1 else 0 end)=1;"}
      ' | dosql
    
por 28.06.2017 / 07:18
0

Usando o GNU find, podemos fazer isso como:

find . -type f -name Makefile \
-execdir sh -c '
   find . ! -name . -prune -name \*.c -execdir pwd \; -quit
' \;

Em que primeiro procuramos encontrar arquivos regulares chamados Makefile e, em seguida, usando o diretório onde eles devem ser encontrados, inicie um sh que deve iniciar um find apenas para localizar arquivos .c nesse diretório e imprimir o nome do dir ao localizar o primeiro .c e depois desistir prontamente.

    
por 28.06.2017 / 14:43