我有一个名为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
****************************
我在这里缺少什么?
答案 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)
看起来你正在将命令作为单个字符串执行,因此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
但是对于大多数情况下的单行命令,应该这样做。