这是一个在命令行上非常适合我的命令:
find . -type f -exec grep -Hin --include=*.h --include=*.c 'somestring' {} \;
当我运行上述命令并将搜索路径替换为任何路径时,该命令仍然仅显示具有或扩展名.
的文件列表。.c
.h
现在,我想编写一个简单的 bash 脚本,使用与变量值相同的命令,这样我就可以通过较小的修改来执行脚本来执行类似的搜索,而不必重新键入命令。但这就是我遇到逃脱规则噩梦的地方(或者缺乏对它的正确理解!)。
我写了一个脚本,如下所示:
#!/bin/bash
path="/home/vinod"
string="somestring"
command="find ${path} -type f -exec grep -Hin --include=*.h --include=*.c '${string}' {} \;"
echo $command
$command
当我运行上面的脚本时,命令回显两次而不是一次,如下所示
find . -type f -exec grep -Hin --include=*.h --include=*.c 'somestring' {} \;
find . -type f -exec grep -Hin --include=*.h --include=*.c 'somestring' {} \;
以及以下运行时错误:
find: missing argument to -exec
从 echo 中可以看出,该命令与我在命令行上运行它时的命令完全相同,我得到了预期的结果。
对我的脚本可能有什么问题有什么想法吗?
TIA
答案1
不要使用变量来存储命令。相反,使用变量来存储数据并使用函数来存储(定义)命令。
我们可以创建一个带有两个参数的命令:起始搜索路径和搜索字符串。
如果您的起始搜索路径也是固定的,您可以简单地修改它以仅采用搜索模式。事实上,让我们颠倒参数的顺序,如果省略搜索路径,则默认为您的$HOME
目录:
#!/bin/sh
# Search in *.c and *.h files for a matching pattern
#
pattern=$1
path=${2:-$HOME}
find "${path:-.}" -type f \( -name '*.c' -o -name '*.h' \) -exec grep -Hin -- "$pattern" {} +
将其保存为文件chfind
,使其可执行(chmod a+rx chfind
),然后将其放在$PATH
.您现在可以像任何其他实用程序一样使用它:
chfind 'main'
chfind 'main' /some/other/tree/of/files
因为我们没有使用grep -F
搜索字符串实际上是正则表达式而不是普通字符串,所以搜索诸如这样的声明FILE *fp
将不起作用。
最后,如果您希望路径名相对于您的搜索路径,您可以将目录更改为$path
,然后从那里搜索:
cd "$path" &&
find -- * -type f \( -name '*.c' -o -name '*.h' \) -exec grep -Hin -- "$pattern" {} +
可能值得解释一下如何通过函数而不是在脚本中内嵌来实现这一点。我已经解决了您的基本要求(“我想编写一个简单的 bash 脚本 [...],以便我可以执行脚本 [...] 进行类似的搜索,而不必重新输入命令”)。但是如果你想使用一个函数,它几乎是完全一样的:
#!/bin/bash
# Search in *.c and *.h files for a matching pattern
#
chFind() {
local pattern=$1 path=$2
find "${path:-.}" -type f \( -name '*.c' -o -name '*.h' \) -exec grep -Hin -- "$pattern" {} +
}
chFind "$1" "${2:-$HOME}"