将命令作为参数传递给 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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 05:03:35  来源:igfitidea点击:

pass a command as an argument to bash script

bash

提问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 和 subshel​​l,那么把你的参数放在他们可以看到彼此:

#! /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

##代码##