我正在尝试编写一些 bash 脚本来替换我经常使用的命令。这是我的文件中的代码test.sh
#!/bin/bash
echo -e "\n"
i=0
args[i++]=$0
for arg in $@ ; do
args[i++]=$arg
done
where="."
what="-type f"
gcase=
str=
while getopts "d:f:F:ih" opt ; do
case $opt in
h)
echo -e "This is the help of this search function."
echo -e "\t $0 [-d <dir>] [-f|-F <pattern>] [-i] string"
echo -e "This will output the result of"
echo -e "\t find dir -[i]name pattern -exec grep --color -Hn[i] string {} \;"
echo -e "Default is"
echo -e "\t find . -type f -exec grep --color -Hn string {} \;\n"
exit 0
;;
d)
OPTIND=$(($OPTIND-1))
where=
tmp=${args[$OPTIND]}
while [[ $OPTIND -lt $# ]] && [[ "${tmp:0:1}" != "-" ]] ; do
where="$where"" $tmp"
OPTIND=$(($OPTIND+1))
tmp=${args[$OPTIND]}
done
;;
F)
what="-iname "
what="$what""\"$OPTARG\""
;;
f)
what="-name "
what="$what""\"$OPTARG\""
;;
i)
gcase="-i"
;;
\?)
echo "Invalide option, use option -h for help." >&2
exit 0
;;
esac
done
str=${args[$OPTIND]}
command="find $where $what -exec grep --color -Hn $gcase \"$str\" {} \;"
echo "$command"
$command
现在,从我的终端,我这样做了./test.sh -d auto-avoid -F "TEST*" "main"
,我得到了
find auto-avoid -iname "TEST*" -exec grep --color -Hn "main" {} \;
find: missing argument to `-exec'
(auto-avoid
是一个目录,其中包含我为了好玩而编写的一个小型 C++ 程序。)
然后,在我的终端中复制粘贴命令find auto-avoid -iname "TEST*" -exec grep --color -Hn "main" {} \;
,然后得到
auto-avoid/test.cpp:26:int main(int argc, char **argv)
这是预期的结果。
问题是:我错过了什么?
现在,我将其编写为独立脚本来测试它,但目标是将其作为我的.bash_aliases
.
我发现了一些类似的主题,但没有什么可以帮助我。如果您发现这是一个重复的问题,我很乐意接受解决方案。
我很确定有些人会告诉我使用grep -r
,但我至少想了解为什么我的脚本不起作用。这是一个最小的“不”工作示例,我稍后会排除一些目录find
。
答案1
使用set -x
查看 shell 真正尝试运行的内容:
$ command='find foo -iname "TEST*" -exec grep --color -F -Hn "main" {} \;'
$ echo "$command"
find foo -iname TEST* -exec grep --color -F -Hn main {} \;
$ set -x
$ $command
+ find foo -iname 'TEST*' -exec grep --color -F -Hn main '{}' '\;'
find: missing argument to `-exec'
请注意'\;'
:您给出的是find
字面上的反斜杠,这不是它所期望的。
双引号完成与反斜杠相同的功能,转义分号,以便将其视为字符,而不是命令分隔符。
这些应该是等效的:
$ foo="something ;"
$ foo=something\ \;
另外,请注意,运行命令行$command
有点麻烦:如果在生成的命令的任何参数中都有空格(例如,在 中的路径名中$where
),它们将被分割。壳阵列提供一种更强大的方法来做到这一点。