我有某些文件夹中同时包含 .c 和 Makefile。我需要知道哪些文件夹有这个。我在linux中输入什么命令才能找到这些文件夹?
答案1
和zsh
:
has() ()(($#)) $REPLY/$~1(N)
ls -- **/*(/e{has Makefile}e{has \\*.c})
has
定义为一个函数,用于检查作为参数给出的 glob 是否解析为$REPLY
目录中的任何文件。我们在 glob 限定符中使用该函数e
来决定是否选择目录。其中的一些 zsh 功能:
() {compound-command} arguments
: 匿名函数。这里该函数的代码是(($#))
,如果参数数量非零则返回 true$~1
:zsh
参数扩展时默认不进行 split+glob 操作。您必须明确请求它$~1
才能请求全局的扩展部分$1
,即被$1
视为一种模式。(N)
: 启用的全局限定符空球对于该 glob,即告诉 glob 如果与任何文件都不匹配,则将其扩展为空。**/
:任何级别的子目录(/e...)
:另一个 glob 限定符,/
仅匹配文件类型目录,并且e{code}
匹配的文件代码解析为 true (文件存储在 中$REPLY
)。
D
如果您想查看隐藏目录并考虑隐藏c
文件,请添加一些glob 限定符:
printf '%s\n' **/*(D/e{has Makefile}e{'has "*.c(#qD)"'})
使用 GNU 工具:
LC_ALL=C find . \( -name '*.c' -o -name Makefile \) -print0 |
LC_ALL=C awk -v RS='\0' -v ORS='\0' '
{dirname = $0; sub("/[^/]*$", "", dirname)}
/\.c$/ {hasc[dirname]; next}
{hasMakefile[dirname]}
END {for (dir in hasc) if (dir in hasMakefile) print dir}' |
xargs -r0 ls
如果您不想进入隐藏目录,并且不考虑隐藏的 C 文件,请将命令更改find
为:
LC_ALL=C find . -name '.?*' -prune -o \( -name '*.c' -o -name Makefile \) -print0
这些将给出匹配目录的路径和内容,但如果只有一个匹配目录,ls
则不会输出其路径。如果您只需要匹配目录的路径,则可以替换ls --
为。printf '%s\n'
答案2
这不是一个严肃的答案,但这样的问题有时会让我们希望使用 SQL-in-shell,或者也许相反,比如:
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
答案3
使用 GNU find,我们可以这样做:
find . -type f -name Makefile \
-execdir sh -c '
find . ! -name . -prune -name \*.c -execdir pwd \; -quit
' \;
其中我们首先寻找名为 Makefile 的常规文件,然后使用要找到它们的目录,启动 sh ,该 sh 将启动 find 仅在该目录中查找 .c 文件,并在找到第一个 .c 文件时打印目录名称。 c 然后立即退出。