首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >编写Shell脚本的shell脚本

编写Shell脚本的shell脚本
EN

Stack Overflow用户
提问于 2010-09-05 20:31:21
回答 3查看 644关注 0票数 0

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

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

如果你不明白我在做什么,我会:

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

2)对$i的每个值进行cd‘’ing,并对其内容进行ls

3)通过cat将其内容回显到带有目录名的新脚本中

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

代码语言:javascript
复制
#/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
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-09-05 22:13:00

您滥用猫科动物很多-您应该简单地重定向,而不是管道到cat的附加。

通过将通过管道定向到shell的单个I/O重定向发送到文件的所有输出捆绑在一起,可以避免中间$i.sh文件-不需要清理中间文件(您没有显示发生这种情况)或chmod操作。

我会使用大括号来实现:

代码语言:javascript
复制
{
echo "..."
ls
echo "..."
} | sh

然而,当我看到这种形式的脚本时,我意识到这是不必要的。我保留了脚本的初始部分不变,但循环要简单得多,如下所示:

代码语言:javascript
复制
#/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 (我会使用base64编码,留给我自己的设备):

代码语言:javascript
复制
    do uuencode $q $q | mailx -s "File $q" $i@tumblr.com

该脚本还使用括号将cd命令括起来。这意味着cd命令和随后的命令是在子shell中运行的,因此父脚本不会更改目录。在这种情况下,如果有$SPECIALDIR的绝对路径名,那就没什么关系了。但作为一般规则,如果像这样隔离目录更改,通常会使工作变得更容易。

为了更好地重用,我可能会进一步简化它(尽管我需要添加一些东西来确保SPECIALPATH被适当地设置):

代码语言:javascript
复制
#/bin/sh

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

然后,我可以使用以下命令调用它:

代码语言:javascript
复制
script-name $(<list-of-dirs)

这意味着在不编辑脚本的情况下,它可以重用于任何目录列表。

中间步骤1:

代码语言:javascript
复制
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:

代码语言:javascript
复制
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,如果有剩余字段,则将其读入$junk。如果您准确地生成了数据,就不会有任何垃圾;但有时您必须处理其他人的数据。

票数 5
EN

Stack Overflow用户

发布于 2010-09-05 21:48:05

如果生成的脚本是临时的,我就不会使用文件。此外,将它们更改为可执行文件听起来不安全。当我需要并行编写脚本时,我使用bash脚本将一组命令(在数组中,将数组一分为二,然后内爆数组)形成单个\n-separated字符串,然后将其传递给一个新的bash实例。

基本上,在bash中:

代码语言:javascript
复制
for orig in "$@"
do
    commands="$commands echo \"echoeing stuff here for arguments $orig\" \n"
done 

echo -e $commands |bash 

还有一个小技巧:如果脚本不需要监督,那么在管道bash后面抛出一个&,让您的第一个脚本退出,并完成派生后台的其余工作。

票数 1
EN

Stack Overflow用户

发布于 2010-09-05 22:03:35

如果导出变量

代码语言:javascript
复制
export VAR1=FOO

它会出现在任何子进程中。

如果您查看init脚本/etc/init..d/*,您会注意到许多脚本都来自另一个充满“外部”定义文件。您可以设置一个这样的文件,并让您的子脚本源这些文件。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3646059

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档