0

问题:
我有一个文件名列表,filenames.txt:例如。

/usr/share/important-library.c
/usr/share/youneedthis-header.h 
/lib/delete/this-at-your-peril.c

我需要重命名或删除这些文件,并且需要在项目目录树中找到对这些文件的引用:/home/noob/my-project/以便删除或更正它们。

我的想法是使用 bash 提取文件名:basename filename,然后使用 for 循环在项目目录中对其进行 grep。

FILELISTING=listing.txt
PROJECTDIR=/home/noob/my-project/

for f in $(cat "$FILELISTING"); do
    extension=$(basename ${f##*.})
    filename=$(basename ${f%.*})
    pattern="$filename"\\."$extension"
    grep -r "$pattern" "$PROJECTDIR"
done

我可以彻底搞砸这个项目——有人看到我的逻辑有缺陷吗?更好:您是否看到在巨大的目录树上执行此操作的更可靠的可扩展方式?让我们假设修订控制不在讨论范围内(实际上是这样)。

4

2 回答 2

5

几点评论:

  • 代替

    for f in $(cat "$FILELISTING") ; do
        ...
    done
    

    写起来更安全一些

    while IFS= read -r f ; do
        ...
    done < "$FILELISTING"
    

    这样,您的代码就不会出现文件名中的空格、制表符、星号等问题(尽管它仍然不支持换行符)。

  • 您分离fextensionand filename,然后用 重新组装它们的目标\.似乎是您希望将文件名视为文字字符串;正确的?就像,您担心grep会将其.视为“任何字符”而不是“一个点”。更通用的解决方案是使用grep's-F选项,它告诉它将模式视为固定字符串而不是正则表达式:

    grep -r -F "$f" "$PROJECTDIR"
    
  • 您的介绍提到 using basename,但实际上您并没有使用它。这是故意的吗?

  • 如果您basename有意不使用,那么filenames.txt实际上只包含要搜索的模式列表;在这种情况下,您甚至不需要编写循环,因为grep'-f选项告诉它从文件中获取以换行符分隔的模式列表:

    grep -r -F -f "$FILELISTING" "$PROJECTDIR"
    

  • 你应该备份你的项目,使用类似tar -czf backup.tar.gz "$PROJECTDIR". “修订控制不可用”并不意味着您不能有回滚策略!

编辑添加:

  • 要一次传递所有基本名称grep,希望它可以对它们做一些更智能的事情,而不是像调用是分开的那样循环它们,你可以编写如下内容:

    grep -r -F "$(sed 's#.*/##g' "$FILELISTING")" "$PROJECTDIR"
    

    (为简洁起见,我使用sed而不是while+ ,但如果您愿意basename,您可以在内部使用整个循环。)"$(...)"

于 2013-05-24T20:18:32.980 回答
1

这是 IDE 的工作。

没错,这是一项危险的任务,除非您知道构建过程和搜索目录以及目录的顺序,否则您真的无法说出哪个文件的标题。

让我们像这样简单:

# include "sql.h"

您在项目中有一个文件headers/sql.h。需要那个文件吗?也许是的。也许不吧。还有一个/usr/include/sql.h。也许这就是实际使用的那个。如果不查看并查看包含Makefile目录的顺序,您将无法判断哪个是哪个。

然后,有一些库被包含在内,可能需要它们自己的头文件才能编译。而且,一旦你使用了 C 预处理器,你真的会很难过。

这是 IDE(集成开发环境)的任务。IDE 构建项目并跟踪文件和其他资源依赖项。在 Java 世界中,大多数人使用 Eclipse,并且为这些开发人员提供了一个 C/C++ 插件。但是,维基百科中列出了超过 2 打,并且几乎所有这些都是开源的。最好的将取决于您的环境。

于 2013-05-24T20:54:25.707 回答