别名在定义它的外壳内部。它对其他进程不可见。Shell函数也是如此。xargs
是一个单独的应用程序,它不是外壳程序,因此没有别名或函数的概念。
您可以使xargs调用Shell而不是grep
直接调用。但是,仅调用Shell是不够的,您还必须在该Shell中定义别名。如果您在中定义了别名,则.bashrc
可以获取该文件。但是,这可能对您.bashrc
执行非交互式shell中没有意义的其他任务无效。
find . -name '*.py' | xargs bash -c '. ~/.bashrc; grep -E regex_here "$@"' _
键入正则表达式时,请注意嵌套引用的复杂性。您可以通过将regexp作为参数传递给Shell来简化生活。
find . -name '*.py' | xargs bash -c '. ~/.bashrc; grep -E "$0" "$@"' regex_here
您可以显式执行别名查找。然后xargs
会看到grep -n --color=always
。
find . -name '*.py' | xargs "${BASH_ALIASES[grep]}" regex_here
在zsh中:
find . -name '*.py' | xargs $aliases[grep] regex_here
顺便说一句,请注意,find … | xargs …
其中包含空格的文件名会中断(以及其他)。您可以通过更改为以空分隔的记录来解决此问题:
find . -name '*.py' -print0 | xargs -0 "${BASH_ALIASES[grep]}" regex_here
或使用-exec
:
find . -name '*.py' -exec "${BASH_ALIASES[grep]}" regex_here {} +
无需调用find
,您可以完全在shell内完成所有操作。全局模式以**/
递归方式遍历目录。在bash中,您需要先运行shopt -s globstar
以启用该glob模式。
grep regex_here **/*.py
这有一些限制:
- 如果有很多文件匹配(或文件路径较长),则该命令可能会失败,因为它超过了命令行的最大长度。
- 在bash≤4.2中(但不是在较新的版本中,也不在ksh或zsh中),
**/
递归到指向目录的符号链接中。
如MariusMatutiae所建议,另一种方法是使用过程替换。
grep regex_here <(find . -name '*.py')
当**/
不适用时,这很有用:对于复杂的find
表达式,或者当您不想在符号链接下递归时,在bash≤4.2中使用。请注意,这会破坏包含空格的文件名;一种解决方法是设置IFS
和禁用globlob,但是它开始变得有点复杂:
(IFS=$'\n'; set -f; grep regex_here <(find . -name '*.py') )