编写shell脚本的Shell脚本

时间:2010-09-05 12:31:21

标签: linux unix shell

两个问题:如何将此脚本中的shell变量写入其子脚本?

有没有更简单的方法可以做到这一点?

如果你不能按照我的意思行事,我就是:

1)从一个目录列表开始,这些目录的名称将存储为$ i

所取的值

2)cd'ing到$ i的每个值并且ls的内容

3)通过cat

将其内容回显到具有目录名称的新脚本中

4)使用echo和cat编写一个包含$ i的ls'd值的新脚本,并将它们全部发送到名为$i@tumblr.com的博客电子邮件地址

#/bin/sh
read -d '' commands <<EOF

#list of directories goes here
dir1
dir2
dir3
etc...    

EOF

for i in $commands
do

cd $SPECIALPATH/$i
echo ("#/bin/sh \n read -d '' directives <<EOF \n") | cat >> $i.sh
ls | cat >> $i.sh
echo ("EOF \n for q in $directives \n do \n uuencode $q $q | sendmail $i \n done \n") | cat >> $i.sh
# NB -- I am asking the script to write the shell variable $i into the new
# script, called $i.sh, as the email address specified, in the middle of an
# echo statement... I am well aware that it doesn't work as is
chmod +x $i.sh
./$i.sh    

done

3 个答案:

答案 0 :(得分:5)

你正在滥用猫科动物 - 你应该简单地重定向,而不是通过管道追加cat

您可以通过将所有输出到文件的输出与一个直接管道导入shell的I / O重定向捆绑在一起来避免中间$i.sh文件 - 无需清理中间文件(您没有“显示正在发生的事情”或chmod操作。

我会用大括号做到这一点:

{
echo "..."
ls
echo "..."
} | sh

但是,当我以那种形式查看脚本时,我意识到没有必要。我已经保留了脚本的初始部分,但循环非常简单:

#/bin/sh
read -d '' commands <<EOF

#list of directories goes here
dir1
dir2
dir3
etc...    

EOF

for i in $commands
do
    (
    cd $SPECIALPATH/$i
    ls |
    while read q
    do uuencode $q $q | sendmail $i
    done
    )
done

我假设sendmail命令有效 - 这不是我尝试发送电子邮件的方式。我可能会使用mailx或类似的东西,我也会避免使用uuencode(我会使用base-64编码,留给我自己的设备):

    do uuencode $q $q | mailx -s "File $q" $i@tumblr.com

该脚本还使用cd命令周围的括号。这意味着cd命令及其后续内容在子shell中运行,因此父脚本不会更改目录。在这种情况下,使用$ SPECIALDIR的绝对路径名,无关紧要。但作为一般规则,如果您隔离目录更改,通常会使生活更轻松。

我可能会进一步简化它以进行一般性重用(尽管我需要添加一些内容以确保正确设置SPECIALPATH):

#/bin/sh

for i in "$@"
do
    (
    cd $SPECIALPATH/$i
    ls |
    while read q
    do uuencode $q $q | sendmail $i
    done
    )
done

然后我可以用:

调用它
script-name $(<list-of-dirs)

这意味着如果不编辑脚本,它可以重用于任何目录列表。


中级步骤1:

for i in $commands
do
    (
    cd $SPECIALPATH/$i
    {
    echo "read -d '' directives <<EOF"
    ls 
    echo "EOF"
    echo "for q in $directives"
    echo "do"
    echo "    uuencode $q $q | sendmail $i"
    echo "done"
    } |
    sh
    )
done

就个人而言,如果生成的代码使生成的脚本清晰 - 使用多个echo命令,我发现更容易阅读生成的脚本。这包括缩进代码。

中级步骤2:

for i in $commands
do
    (
    cd $SPECIALPATH/$i
    {
    ls |
    echo "while read q"
    echo "do"
    echo "    uuencode $q $q | sendmail $i"
    echo "done"
    } |
    sh
    )
done

我不需要将数据读入变量,以便逐步遍历列表中的每个项目 - 只需依次读取每一行。 while read机制通常也可用于将一行拆分为多个变量:while read var1 var2 var3 junk会将第一个字段读入$var1,第二个字段读入$var2,第三个字段读入$var3 {1}},如果遗留任何内容,则会进入$junk。如果你准确地生成了数据,就不会有任何垃圾;但有时你必须处理其他人的数据。

答案 1 :(得分:1)

如果生成的脚本是临时的,我不会使用文件。此外,将它们调整为可执行的声音不安全。当我需要并行编写脚本时,我使用了一个bash脚本来形成一组命令(在一个数组中,将数组拆分为两个,然后将数组内爆)到一个\n - 分隔的字符串,然后传递给它到一个新的bash实例。

基本上,在bash:

for orig in "$@"
do
    commands="$commands echo \"echoeing stuff here for arguments $orig\" \n"
done 

echo -e $commands |bash 

还有一个小提示:如果脚本不需要监督,请在管道&之后输入bash以使您的第一个脚本退出并完成剩下的工作分叉背景。< / p>

答案 2 :(得分:1)

如果您导出变量

export VAR1=FOO

它将出现在任何子流程中。

如果你看一下init脚本/etc/init..d/*,你会注意到很多来源的文件充满了“外部”定义。您可以设置这样的文件,让您的子脚本来源这些文件。