将命令作为参数传递给 bash 脚本
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15749618/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
pass a command as an argument to bash script
提问by One Two Three
How do I pass a command as an argument to a bash script? In the following script, I attempted to do that, but it's not working!
如何将命令作为参数传递给 bash 脚本?在下面的脚本中,我试图这样做,但它不起作用!
#! /bin/sh
if [ $# -ne 2 ]
then
echo "Usage: ./myscript thisDir echo
<dir> <command to execute>"
exit 1;
fi;
while read line
do
$() $line
done < $(ls );
echo "All Done"
A sample usage of this script would be
此脚本的示例用法是
while read line ; do
$line
done < $(ls )
Executing the call above ought to echo the name of all files in the thisDirdirectory.
执行上面的调用应该回显thisDir目录中所有文件的名称。
回答by shellter
your command "echo" command is "hidden" inside a sub-shell from its argments in $line.
您的命令“echo”命令从 $line 中的参数“隐藏”在子外壳中。
I think I understand what your attempting in with $($2), but its probably overkill, unless this isn't the whole story, so
我想我理解你的尝试$($2),但它可能有点矫枉过正,除非这不是故事的全部,所以
$( $line)
should work for your example with thisDir echo. If you really need the cmd-substitution and the subshell, then put you arguments so they can see each other:
应该适用于您的示例thisDir echo。如果你真的需要 cmd-substitution 和 subshell,那么把你的参数放在他们可以看到彼此:
#! /bin/sh
if [ $# -ne 2 ]; then
echo "Usage: #! /bin/sh
if [ $# -lt 2 ]; then
echo "Usage: echo " $line"|sh
<dir> <command to execute> [command options]"
exit 1
fi
dir=""
shift
for file in "$dir"/*; do
"$@" "$file"
done
echo "All done"
<dir> <command to execute>"
exit 1
fi
for file in ""/*; do
"$file"
done
echo "All done"
And as D.S. mentions, you might need evalbefore either of these.
正如 DS 所提到的,您可能需要eval在其中任何一个之前。
IHTH
IHTH
回答by Gordon Davisson
First big problem: $($2) $lineexecutes $2by itself as a command, then tries to run its output (if any) as another command with $lineas an argument to it. You just want $2 $line.
第一个大问题:作为命令自行$($2) $line执行$2,然后尝试将其输出(如果有)作为另一个命令运行,并将其$line作为参数。你只想要$2 $line.
Second big problem: while read ... done < $(ls $1)doesn't read from the list of filenames, it tries to the contents of a file specified by the output of ls -- this will fail in any number of ways depending on the exact circumstances. Process substitution (while read ... done < <(ls $1)) would do more-or-less what you want, but it's a bash-only feature (i.e. you muststart the script with #!/bin/bash, not #!/bin/sh). And anyway it's a bad idea to parse ls, you should almost always just use a shell glob (*) instead.
第二个大问题:while read ... done < $(ls $1)不从文件名列表中读取,它尝试读取 ls 输出指定的文件的内容——这将根据具体情况以多种方式失败。进程替换 ( while read ... done < <(ls $1)) 或多或少会做你想做的事,但它是一个 bash-only 特性(即你必须用开始脚本#!/bin/bash,而不是#!/bin/sh)。无论如何,解析 ls是一个坏主意,您几乎总是应该只使用 shell glob ( *) 来代替。
The script also has some other potential issues with spaces in filenames (using $linewithout double-quotes around it, etc), and weird stylistic oddities (you don't need ;at the end of a line in shell). Here's my stab at a rewrite:
该脚本还存在一些其他潜在问题,即文件名中的空格(使用时$line不使用双引号等)和奇怪的风格(;在 shell 中的行尾不需要)。这是我对重写的尝试:
eval " $line"
Note that I didn't put double-quotes around $2. This allows you to specify multiword commands (e.g. ./myscript thisDir "cat -v"would be interpreted as running the catcommand with the -voption, rather than trying to run a command named "cat -v"). It would actually be a bit more flexible to take all arguments after the first one as the command and its argument, allowing you to do e.g. ./myscript thisDir cat -v, ./myscript thisDir grep -m1 "pattern with spaces", etc:
请注意,我没有在$2. 这允许您指定多字命令(例如,./myscript thisDir "cat -v"将被解释为运行cat带有-v选项的命令,而不是尝试运行名为 的命令"cat -v")。它实际上会更灵活一些,采取一切争论的第一个作为命令及其参数之后,让你做如./myscript thisDir cat -v,./myscript thisDir grep -m1 "pattern with spaces"等:
回答by Kent
you could try: (in your codes)
你可以试试:(在你的代码中)
##代码##or the eval:
或eval:

