如何使用在.bashrc文件中定义的bash函数与find -exec一起运行

17

我的 .bashrc 文件里有如下函数

function myfile {
 file $1
}
export -f myfile

当我直接调用它时,它能正常工作。

rajesh@rajesh-desktop:~$ myfile out.ogv 
out.ogv: Ogg data, Skeleton v3.0

当我尝试通过exec来调用它时,它不起作用。

rajesh@rajesh-desktop:~$ find ./ -name *.ogv -exec myfile {} \;
find: `myfile': No such file or directory
有没有一种方法可以使用exec调用Bash脚本函数?
非常感谢任何帮助。
更新:
感谢Jim的回复。
但这正是我首先想要避免的,因为我在我的Bash脚本中定义了许多实用函数,我希望将它们与其他有用的命令(例如find-exec)一起使用。
尽管我完全理解你的观点,但find可以运行可执行文件,它不知道传递的参数是在脚本中定义的函数。
当我在Bash提示符上尝试执行时,我将得到相同的错误。
$ exec myfile out.ogv

我希望能有一些巧妙的诀窍,让exec执行一个虚构的命令,例如“bash -myscriptname -myfunctionname”。

我想我应该尝试找到一种方法来动态创建一个bash脚本,并使用exec运行它。


这不是一个论坛。请不要将回复作为答案发布,除非它们是。 - Dennis Williamson
1
我这么做的原因是添加评论不允许您添加代码。 - sharrajesh
1
但编辑您自己的原始帖子可以让您添加任意数量的代码,并且更清晰。 - msw
8个回答

7
find ./ -name *.ogv -exec bash -c 'myfile {}' \;

2
你应该引用文件名:bash -c 'myfile "{}"' - Janus
很确定bash命令不会按照你的方式扩展变量。我认为它应该是 bash -c 'myfile "$0"' {} \; - JellicleCat

7
我设法以更优雅的方式运行它,可能是这样的:
function myfile { ... }
export -f myfile
find -name out.ogv -exec bash -c '"$@"' myfile myfile '{}' \;

请注意,myfile被重复使用了两次。第一次是脚本的$0参数(在这种情况下,它基本上可以是任何内容)。第二次是要运行的函数名称。

6
$ cat functions.bash
#!/bin/bash

function myecho { echo "$@"; }
function myfile { file "$@"; }
function mycat { cat "$@"; }

myname=`basename $0`
eval ${myname} "$@"
$ ln functions.bash mycat
$ ./mycat /etc/motd
Linux tallguy 2.6.32-22-core2 ...
$ ln functions.bash myfile
$ myfile myfile
myfile: Bourne-Again shell script text executable
$ ln functions.bash myecho
$ myecho does this do what you want\?
does this do what you want?
$ 

当然,在实际情况中,这些函数可能比我的示例复杂一些。


5
您可以通过将命令放入Bash的标准输入来运行函数:
bash$ find ./ -name *.ogv -exec echo myfile {} \; | bash

上面的命令对于你的例子可以起作用,但是你需要注意所有的“myfile…”命令都是一次生成并发送到单个bash进程中的。

这看起来也不错。它按照我的预期在我的情况下工作了。谢谢。 - sharrajesh

3

我认为find无法做到这一点,因为执行命令的是find命令本身,而不是您当前运行的shell...因此bash函数或别名不能在那里工作。如果您将函数定义转换为一个名为myfile的单独的bash脚本,使其可执行,并将其安装在某个路径上,find应该会正确地处理它。


3

更简单

function myfile { echo $* ; }
export -f myfile

find . -type f -exec bash -c 'myfile "{}"'  \;

这个非常好用,谢谢!导出选项“-f”是什么意思?我在函数后面加上它之后,它就起作用了!之前我只有“export myfile”。 - Benxamin
1
-f 表示将该项导出为函数而不是变量。 - kdubs
1
我刚刚又尝试了一下,从命令行无法运行(我怀疑是shell shock补丁的问题),但如果我把所有内容放在一个文件中,它就可以工作。 - kdubs
我追踪到了一个Shell Shocked之前的Bash版本。对于那个版本,它在命令行上可以工作。在Shell Shocked之后,你需要从脚本中执行它(为什么?)。@KevinBuchs请重新考虑你的反对票。 - kdubs
最后更新日期,如果您正在使用兼容版本的bash,则可以从命令行工作。我的登录shell bash与我的路径中的bash版本不同,并且它们无法一起工作。因此,如果bash版本兼容,它将从命令行工作。 - kdubs

2
子shell脚本似乎会保留父函数,因此您可以编写类似于以下示例的脚本:

'runit.sh'

#! /bin/bash

"$@"

然后执行 find -name out.ogv -exec ./runit.sh myfile '{}' \;,它就可以正常工作了! :)


谢谢Joao。这看起来是一个非常聪明和优雅的解决方案。只有一个小问题,我必须先为我的脚本提供源以运行myfile函数,例如我从你的建议中借鉴并将我的runint.sh改为以下形式:#!/bin/bash script_name=$1 func_name=$2 func_arg=$3 source $script_name $func_name $func_arg否则我会得到:$ find ./ -name *.ogv -exec ./runit.sh myfile {} \; ./runit.sh: 1: myfile: not found非常感谢。 - sharrajesh
不要从 runit.sh 中获取脚本,你可以在使用之前让脚本导出函数(export -f myfile)。 - Gordon Davisson
我以为他是在他的.bashrc文件中这样做。那么它应该可以正常工作,对吧? - João Portela

1

谢谢Joao。这看起来是非常聪明和优雅的解决方案。小问题是我必须先获取我的脚本才能运行myfile函数,例如,我从您的建议中借鉴并将我的runint.sh修改为以下内容

#!/bin/bash
script_name=$1
func_name=$2
func_arg=$3
source $script_name
$func_name $func_arg

现在我可以按照以下方式运行它

$ find ./ -name *.ogv -exec ./runit.sh ~/.bashrc myfile {} \;
./out.ogv: Ogg data, Skeleton v3.0

否则我会得到:
$ find ./ -name *.ogv -exec ./runit.sh myfile {} \;
./runit.sh: 1: myfile: not found

无论如何,非常感谢。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接