如何查找包含源的所有目录?

时间:2015-04-10 20:05:45

标签: linux bash

我有一个目录很少的项目(事先并不知道所有目录)。我想发出一个命令来查找包含源的所有目录。像find . -name "*.cpp"这样的东西会给我一个源列表,而我只想要一个包含它们的目录列表。项目结构事先不知道,目录X中可能存在某些源,而子目录X / Y中可能存在其他源。将打印包含源的所有目录列表的命令是什么?

6 个答案:

答案 0 :(得分:5)

find . -name "*.cpp" -exec dirname {} \; | sort -u

如果(a)您有GNU find或最新版本的BSD find和(b)您有最新版本的dirname(例如GNU coreutils 8.21或FreeBSD 10)但 OSX 10.10),那么,为了提高效率,请使用(帽子提示:Jochen和mklement0):

find . -name "*.cpp" -exec dirname {} + | sort -u

答案 1 :(得分:3)

John1024's answer 优雅快速如果您的dirname版本支持多个参数< / strong>,您可以使用-exec dirname {} +调用它。

否则,对于-exec dirname {} \;,子进程会为每个输入文件名分叉,这很慢。

如果:

  • 您的dirname不支持多个参数
  • 和表现很重要
  • 您正在使用bash 4或更高版本

考虑以下解决方案:

shopt -s globstar; printf '%s\n' ./**/*.cpp | sed 's|/[^/]*$||' | sort -u
  • shopt -s globstar激活对跨目录路径名扩展(globbing)的支持
  • ./**/**.cpp然后匹配当前目录的子树

    中的.cpp个文件
    • 请注意,glob故意以./开头,因此下面的sed命令也会正确报告顶级目录本身,如果它包含匹配的文件。< / LI>
  • sed 's|/[^/]*$||'有效地执行与dirname相同的操作,但在所有输入行上执行调用{{1} }}

  • sed对结果进行排序,并仅输出唯一的目录名称。

答案 2 :(得分:1)

find . -name "*.cpp" | while read f; do dirname "$f" ; done | sort -u

应该做你需要的事情

答案 3 :(得分:1)

find . -name '*.cpp' | sed -e 's/\/[^/]*$//' | sort | uniq

答案 4 :(得分:1)

简单地找到非空目录:

$ find . \! -empty -type d

对于只包含特定文件类型的目录,我会使用以下内容:

find . -name \*.cpp | while read line; do dirname "${line}" ; done | sort -u

这会查找所有* .cpp文件,并在每个文件名上调用dirname。然后对结果进行排序并使其唯一。使用不需要为每个* .cpp文件生成新进程的shell-builtins,确实有更快的方法。但这对大多数项目来说可能并不重要。

答案 5 :(得分:0)

您应该定义什么是源文件。

请注意某些C或C ++文件生成 (例如,通过bisonyacc等解析器生成器,通过ad-hoc { {1}}或awk或shell脚本,特定于项目的生成器等等,以及一些包含C或C ++文件的文件未命名为python.h(阅读X-macros)。在GCC内生成大量文件(例如,来自.cc机器描述文件,这些文件是可靠的源文件)

大多数大型软件项目(例如数百万行C ++或C代码)已经或正在某处使用某些C或C ++代码生成器。

在自由软件世界中,源代码只是开发人员正在使用的代码的首选表单

请注意,源代码甚至可能不在文件中;它可以放在数据库中,在某些堆映像中,例如如果开发人员正在与特定程序交互工作。 (记住20世纪80年代的Smalltalk机器,或1980年INRIA的Mentor structured editor)。另一个例子是,J.Pitrat的CAIA系统的C代码完全由自己生成。另请参阅Scheme48

也许(仅作为近似启发式)您应该将任何名为*.md.h.cc.cpp或{{1}的文件视为C ++源文件}}或.cxx.def,其中不包含.inc个字词(通常在某些评论中)。

要了解生成的文件是什么,您应该深入了解构建过程(由.tccGENERATED FILEMakefileCMake*等描述......)。 检测或猜测生成的 C ++ 文件没有万无一失的方法;所以你将无法可靠地自动检测。

最后,引导语言通常有一个(版本控制)存储库,其中包含一些生成的文件。 Ocaml有一个boot/ subdirectoryMELT有一个Makefile.am目录(包含从autoconf源代码文件中以C ++形式重新生成MELT所需的C ++文件。)

我建议使用项目版本控制repository并获取非空目录。详细信息取决于version control工具(例如gitmelt/generated/*.melt等...)。您应使用某些版本控制(或版本控制工具。我推荐svn