将一个命令作为参数传递给Bash脚本

11
我该如何将命令作为参数传递给Bash脚本?在下面的脚本中,我尝试这样做,但它没有起作用!
#! /bin/sh

if [ $# -ne 2 ]
then
    echo "Usage: $0 <dir> <command to execute>"
    exit 1;
fi;

while read line
do
    $($2) $line
done < $(ls $1);

echo "All Done"

这个脚本的一个示例用法是:
./myscript thisDir echo

执行上面的调用应该会回显出thisDir目录中所有文件的名称。

1
尝试 eval "$2" - http://www.linuxquestions.org/questions/programming-9/bash-script-passing-command-as-string-476664/ - David Starkey
@DavidStarkey 嗯,我尝试了 eval(以及下面建议的其他与 eval 相关的解决方案),但都没有起作用。 - One Two Three
3个回答

4

第一个大问题: $($2) $line 将会把 $2 当作命令来执行,然后尝试以 $line 为参数运行它的输出(如果有的话)作为另一个命令。你只需要 $2 $line

第二个大问题: while read ... done < $(ls $1) 并不是从文件名列表读取内容,而是尝试读取由 ls 输出的文件的内容 -- 这将因确切情况的不同而失败。进程替换 (while read ... done < <(ls $1)) 可以更或多少达到你想要的效果,但这是 bash 的特性(也就是说,你必须使用 #!/bin/bash 而不是 #!/bin/sh 来启动脚本)。而且总之解析 ls 是个坏主意,你几乎总是应该只使用 shell glob (*)。

该脚本还存在一些潜在的文件名空格问题(未在$line周围使用双引号等),以及奇怪的风格怪异性(在shell中不需要在行末使用;)。以下是我重写的尝试:
#! /bin/sh

if [ $# -ne 2 ]; then
    echo "Usage: $0 <dir> <command to execute>"
    exit 1
fi

for file in "$1"/*; do
    $2 "$file"
done

echo "All done"

请注意,我没有在$2周围放置双引号。这允许您指定多个单词的命令(例如,./myscript thisDir "cat -v"将被解释为使用-v选项运行cat命令,而不是尝试运行名为"cat -v"的命令)。更灵活的方法是将第一个参数后的所有参数作为命令及其参数接受,从而允许您执行例如./myscript thisDir cat -v./myscript thisDir grep -m1 "pattern with spaces"等操作:
#! /bin/sh

if [ $# -lt 2 ]; then
    echo "Usage: $0 <dir> <command to execute> [command options]"
    exit 1
fi

dir="$1"
shift

for file in "$dir"/*; do
    "$@" "$file"
done

echo "All done"

2
你可以尝试:(在你的代码中)
echo "$2 $line"|sh

或者是eval
eval "$2 $line"

对我不起作用。当我使用 myscript thisDir cat 调用脚本时,它应该 cat 目录中的所有文件,但它没有。 - One Two Three
没有任何错误。当我运行脚本时,它只是列出了目录中的所有文件,即使我指定了“cat”作为命令。 - One Two Three
@OneTwoThree 1) ls 命令的结果中可能包含目录,因此无法使用 cat 命令。2) 您可以尝试 ls $1|while read line.....done - Kent

2

您的命令“echo”在$line中的参数中被“隐藏”在子shell中。

我认为我理解了您尝试使用$($2)做什么,但这可能有些过度,除非这不是全部情况,所以

 while read line ; do
    $2 $line
 done < $(ls $1)

如果您的示例是thisDir echo,那么应该能够正常运行。如果您确实需要cmd-substitution和子shell,请将参数放置在彼此可见的位置:

   $($2 $line)

正如D.S.所提到的,您可能需要在这两个之前使用eval

祝您好运!


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