我正在尝试在我的.bashrc
文件中定义以下 bash 函数:
function myfind() {
find $1 -not -path venv -not -path .tox -name "$2" | xargs grep -n "$3"
}
这不是我所期望的。当我使用该功能搜索文件中的文本时,例如
myfind . *.py test
它不返回任何东西。但是当我直接使用表达式时,即
find . -not -path venv -not -path .tox -name "*.py" | xargs grep -n "test"
它返回一些匹配项。
我已经尝试使用双引号,例如
function myfind() {
find $1 -not -path venv -not -path .tox -name '"$2"' | xargs grep -n '"$3"'
}
或者
function myfind() {
find $1 -not -path venv -not -path .tox -name "'$2'" | xargs grep -n "'$3'"
}
并试图逃避像
function myfind() {
find $1 -not -path venv -not -path .tox -name \"$2\" | xargs grep -n \"$3\"
}
但这些似乎都不起作用。
如何修复这个 bash 函数,以便在参数周围“使用”引号?
伊蒂姆:
接着:
另请参阅为什么循环查找的输出是不好的做法?为什么调用类似
xargs
的输出find
是错误的。您的方法的其他一些问题:
-path venv
永远不会匹配任何东西作为-path
正在考虑的文件的完整路径上的匹配,这将类似于<contents-of-$1>/subdir/file
. 只有在调用的顶层myfind venv ...
才会匹配。我假设您想忽略存储在名为venv
. 虽然您可以使用! -path '*/venv/*'
它,但首先告诉find
不要进入这些目录比事后过滤掉其中的所有文件更有效(! -path '*/venv/*'
如果文件路径在语言环境中不是有效文本,也会有问题) .使用
myfind first *.py last
,您要求外壳程序扩展*.py
到当前目录中的匹配文件列表中,以构成 的倒数第二个参数myfind
,而*.py
您希望将其传递给myfind
formyfind
以将其传递给find
after的文字参数-name
,因此需要引用该*
字符,以便它不会被 shell 解释为通配符。在这里,我们用 if or 来引用整个内容*.py
就足够了,因为其他 3 个字符('*.py'
和)对于shell 来说并不是特殊的。'*'.py
\*.py
.
p
y
如果使用 zsh 而不是 bash,则可以
alias myfind='noglob myfind'
在myfind
. 然后你就可以在myfind . *.py test
不*.py
被外壳扩展的情况下做到这一点。必须引用参数扩展以防止 split+glob (
"$1"
, not$1
)。如果没有
-H
(GNU 扩展)如果find
只找到一个文件,则grep
不会打印其路径,因此您将不知道匹配项在哪里。对于grep
不支持的实现,您可以作为额外参数-H
传递: ./dev/null
-exec grep -ne "$3" -- /dev/null {} +
请参阅
!
与非标准等效的标准(或更短)-not
。与
grep -n "$3"
,如果$3
以 开头-
,它将被 视为一个选项grep
。因此,-e "$3"
相反,其中的内容$3
作为参数传递给-e
选项。有同样的问题find "$1"
,但不幸的是,没有标准的解决方法。find -- "$1"
会阻止它的内容$1
被视为以开头的选项,但它仍将被视为谓词,因此毫无意义。例如,一个名为or的目录也是一个问题。BSD可以做到这一点,但 GNU和大多数其他实现不支持它。利用find
-
!
(
find
find -f "$1"
find
find
myfind ./-dir-starting-with-data- '*.py' pattern
传递以破折号开头的目录。代码中唯一不是标准
sh
语法的是function name()
函数定义语法。ksh 语法是function name {...;}
,Bourne 和标准bash
语法是name() {...;}
. 虽然bash
也是function name() { ...; }
偶然支持,但没有真正好的理由使用它。我已将 a 添加
-type f
到仅考虑的常规文件中,因为您可能不想grep
在设备文件或 fifos 中开始搜索,它会报告目录或套接字的错误。使用 GNUfind
,您可以将其替换为,-xtype f
以便最终解析为常规文件的符号链接也被考虑在内。