Bash 脚本 - 在循环中运行带有变量的函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8466535/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 01:09:53  来源:igfitidea点击:

Bash Script - Run Functions with Variables in Loop

bashfunctionloops

提问by nicorellius

I have a share backup bash script that works as is, but it uses several lines to do something that can be looped (I'm hoping). I'm thinking it can be much better, and the first step, in my mind, would be to use a loop to cycle through the shares.

我有一个按原样工作的共享备份 bash 脚本,但它使用多行来执行可以循环的操作(我希望)。我认为它可以好得多,在我看来,第一步是使用循环来循环共享。

In it scurrent state, the script I have calls three bash functions and a python script (that sends email with stderr and stdout) for each share, of which there are several (4 now, and maybe up to 6-8), and it looks like this:

在当前状态下,我的脚本为每个共享调用了三个 bash 函数和一个 python 脚本(发送带有 stderr 和 stdout 的电子邮件),其中有几个(现在是 4 个,可能多达 6-8 个),它看起来像这样:

create_log_dir "$share1_backup"
create_log "$share1_backup" "$log_file"
create_rsync_cmd "$log_file"

python backup.py $email_address \
"$rsync_command $rsync_args $share1 $share1_backup"

So the code above would be something like 20-30 lines for all the shares. I was hoping to make a loop that goes through these steps for each share that looks something like this (pseudocode-like example):

因此,对于所有共享,上面的代码将类似于 20-30 行。我希望为每个看起来像这样的共享创建一个循环,通过这些步骤(类似伪代码的示例):

for var in list (each $share_var and $log_var)
do
  create_log_dir "$share_var"
  create_log "$share_var" "$log_var"
  create_rsync_cmd "$log_var"
done

I tried this format with some bash options and couldn't get it to work. Still new to bash, so I'm hoping to pick up some cool tips with this one.

我用一些 bash 选项尝试了这种格式,但无法让它工作。对 bash 还是新手,所以我希望能从这个技巧中学到一些很酷的技巧。

Thanks in advance.

提前致谢。

UPDATE EDIT

更新编辑

Here are the path and log variables and the for loop I'm using:

这是我正在使用的路径和日志变量以及 for 循环:

#variables
share1="/path/to/share/"
share1_backup="/path/to/share/backup"

# log creation
# If the 'rsync_logs' directory in destination doesn't exist, create it.
create_log_dir()
{
   backup_dest=
   if [ ! -d "$backup_dest/rsync_logs" ]
   then
      mkdir $backup_dest/rsync_logs
   fi
}

# Check for log_file existence; append '_alt' if exists.
create_log()
{
   backup_dest=
   log_file=
   log_file="$backup_dest/rsync_logs/$(date +"%Y-%m%d")_rsync_output.log"
   if [ -f $log_file ]
   then
      log_file="${log_file}_alt"
   fi
}

#loop
for pair in "share1_backup log_file"
do
  set -- $pair
  share=
  log=

  create_log_dir "$share"
  create_log "$share" "$log"
  create_rsync_cmd "$log"
done

So I tried it with the original answer:

所以我用原来的答案试了一下:

for pair in "share1_backup log_file"

for pair in "share1_backup log_file"

and... with the variable method (neither seemed to work - first one gave error because the directory, share1_backup/rsync_logsdidn't exist - it didn't use the variable):

和...使用变量方法(似乎都不起作用 - 第一个错误,因为目录share1_backup/rsync_logs不存在 - 它没有使用变量):

for pair in "${share1_backup} ${log_file}"

for pair in "${share1_backup} ${log_file}"

This second one resulted in empty log file.

第二个导致空的日志文件。

UPDATE EDIT 2

更新 编辑 2

I think the better approach to this, so that the two answers below will both work, is to build the logs somewhere else. I originally thought it'd be nice to save them in the backup destination, but then again, it might be good to save the logs on the machine on which all the shares are mounted, for consistency. Then I can write a script that copies them over periodically, if I must have them on the destination drives. This way, I can build the log_file variable ahead of time, and then use it in the loop, as David K. Hess pointed out.

我认为更好的方法是在其他地方构建日志,以便下面的两个答案都有效。我最初认为将它们保存在备份目标中会很好,但话说回来,为了一致性,将日志保存在安装了所有共享的机器上可能会很好。然后我可以编写一个脚本来定期复制它们,如果我必须将它们放在目标驱动器上。这样,我可以提前构建 log_file 变量,然后在循环中使用它,正如 David K. Hess 指出的那样。

Thanks again.

再次感谢。

回答by David K. Hess

This approach should work as long as your paths don't have spaces in them:

只要您的路径中没有空格,这种方法就应该有效:

for pair in "share1_var log1_var" "share2_var log2_var"
do
    set -- $pair
    share_var = 
    log_var = 
    create_log_dir "$share_var"
    create_log "$share_var" "$log_var"
    create_rsync_cmd "$log_var"
done

回答by choroba

What about using an array? It works even if your values contain spaces.

使用数组怎么样?即使您的值包含空格,它也能工作。

array=("share1" "log1"
       "share2" "log2")
for ((i=0; i<${#array[@]}; i+=2)) ; do
    share_var=${array[i]}
    log_var=${array[i+1]}
    create_log_dir "$share_var"
    create_log "$share_var" "$log_var"
    create_rsync_cmd "$log_var"
done