8

如何将命令作为参数传递给 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目录中所有文件的名称。

4

3 回答 3

2

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

我想我理解你的尝试$($2),但它可能有点矫枉过正,除非这不是全部,所以

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

应该适用于您的示例thisDir echo。如果您真的需要 cmd-substitution 和 subshel​​l,请输入参数,以便它们可以互相看到:

   $($2 $line)

正如 DS 所提到的,您可能需要eval在其中任何一个之前。

IHTH

于 2013-04-01T19:04:11.957 回答
1

第一个大问题:作为命令自行$($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",将被解释为运行cat带有-v选项的命令,而不是尝试运行名为 的命令"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"
于 2013-04-01T20:12:51.723 回答
1

你可以试试:(在你的代码中)

echo "$2 $line"|sh

eval

eval "$2 $line"
于 2013-04-01T19:03:38.513 回答