在bash中执行包含空格的命令

时间:2009-05-07 18:41:39

标签: bash shell

我有一个名为cmd的文件,其中包含一个unix命令列表,如下所示:

hostname
pwd
ls  /tmp
cat /etc/hostname
ls -la
ps -ef | grep java
cat cmd

我有另一个脚本在cmd中执行命令:

IFS=$'\n'
clear
for cmds in `cat cmd`
do
        if [  $cmds ] ; then
        $cmds;
        echo "****************************";
        fi
done

问题是没有空格的cmd中的命令运行正常,但脚本没有正确解释带空格的命令。以下是输出:

patrick-laptop
****************************
/home/patrick/bashFiles
****************************
./prog.sh: line 6: ls  /tmp: No such file or directory
****************************
./prog.sh: line 6: cat /etc/hostname: No such file or directory
****************************
./prog.sh: line 6: ls -la: command not found
****************************
./prog.sh: line 6: ps -ef | grep java: command not found
****************************
./prog.sh: line 6: cat cmd: command not found
****************************

我在这里缺少什么?

6 个答案:

答案 0 :(得分:16)

尝试将一行更改为eval $cmds,而不仅仅是$cmds

答案 1 :(得分:3)

您可以使用命令

替换脚本
sh cmd

shell的工作是读取命令并运行它们!如果需要输出/进度指示器,请以详细模式运行shell

sh -v cmd

答案 2 :(得分:2)

我个人更喜欢这种方法 - 如果我不必这样做,我不想让IFS变得更好。如果要在命令中使用管道,则需要使用eval。管道需要由shell而不是命令处理。我相信shell会在扩展字符串之前解析出管道。

请注意,如果您的cmd文件包含接受输入的命令,则会出现问题。 (但是你总是可以为read命令创建一个新的fd来读取。)

clear
while read cmds 
do
        if [ -n "$cmds" ] ; then
        eval $cmds
        echo "****************************";
        fi
done < cmd

答案 3 :(得分:1)

编辑:结果管道和重定向失败。谢谢,Andomar。

你需要在循环中更改IFS,以便bash知道在哪里拆分参数:

IFS=$'\n'
clear
for cmds in `cat cmd`
do
    if [ $cmds ] ; then
        IFS=$' \t\n' # the default
        $cmds;
        echo "****************************";
        IFS=$'\n'
    fi
done

答案 4 :(得分:0)

编辑:Ben Blank的评论指出我的回答是错误的,谢谢。

看起来你正在将命令作为单个字符串执行,因此bash将它们视为脚本/可执行文件名。

避免这种情况的一种方法是在命令上调用bash。变化:

    if [  $cmds ] ; then
    $cmds;
    echo "****************************";
    fi

    if [  $cmds ] ; then
    bash -c $cmds
    echo "****************************";
    fi

答案 5 :(得分:0)

sed 'aecho "-----------"' cmd > cmd.sh; bash cmd.sh

sed'aXX'将XX添加到每一行。这不适用于多行命令,如:

for f in * 
do 
    something $f
fi

但是对于大多数情况下的单行命令,应该这样做。