bash shell脚本for循环中的两个变量

sno*_*key 10 bash shell scripting for-loop

我是shell脚本的新手.如果我的怀疑太愚蠢,那么请耐心等待我.

我在2个不同的目录中有png图像和一个可执行文件,它从每个目录中获取图像并处理它们以生成新图像.

我正在寻找一个可以同时获取两个变量的for循环结构.这在C,C++等中是可能的,但我如何实现以下内容.代码显然是错误的.

#!/bin/sh

im1_dir=~/prev1/*.png  
im2_dir=~/prev3/*.png
index=0

for i,j in $im1_dir $im2_dir  # i iterates in im1_dir and j iterates in im2_dir 
do
  run_black.sh $i $j  
done
Run Code Online (Sandbox Code Playgroud)

谢谢!

jor*_*anm 13

如果您依赖于两个目录来匹配基于区域设置排序顺序(如您的尝试),那么数组应该可以工作.

im1_files=(~/prev1/*.png)
im2_files=(~/prev3/*.png)

for ((i=0;i<=${#im1_files[@]};i++)); do
   run_black.sh "${im1_files[i]}" "${im2_files[i]}"
done
Run Code Online (Sandbox Code Playgroud)

  • 它不应小于("<")且不等于或小于("<=")吗?在我看来,这需要一个循环时间. (3认同)

Pau*_*ce. 5

以下是一些其他方法来做您正在寻找的有关利弊的说明.

以下仅适用于不包含换行符的文件名.它以锁步方式配对文件.它使用额外的文件描述符从第一个列表中读取.如果im1_dir包含更多文件,则在im2_dir用完时循环将停止.如果im2_dir包含更多文件,file1则对于所有不匹配的文件将为空file2.当然,如果它们包含相同数量的文件,则没有问题.

#!/bin/bash
im1_dir=(~/prev1/*.png) 
im2_dir=(~/prev3/*.png)

exec 3< <(printf '%s\n' "${im1_dir[@]}")

while IFS=$'\n' read -r -u 3 file1; read -r file2
do
    run_black "$file1" "$file2"
done < <(printf '%s\n' "${im1_dir[@]}")

exec 3<&-
Run Code Online (Sandbox Code Playgroud)

您可以使行为保持一致,以便循环停止,只有非空匹配的文件,无论哪个列表更长,通过用双&符号替换分号,如下所示:

while IFS=$'\n' read -r -u 3 file1 && read -r file2
Run Code Online (Sandbox Code Playgroud)

此版本使用for循环而不是while循环.当两个列表中较短的一个用完时,这个停止.

#!/bin/bash
im1_dir=(~/prev1/*.png) 
im2_dir=(~/prev3/*.png)

for ((i = 0; i < ${#im1_dir[@]} && i < ${#im2_dir[@]}; i++))
do
    run_black "${im1_dir[i]}" "${im2_dir[i]}"
done
Run Code Online (Sandbox Code Playgroud)

此版本与上面的版本类似,但是如果其中一个列表用完,它将回绕以重用这些项目,直到另一个项目用完为止.它非常难看,你可以更简单地用另一种方式做同样的事情.

#!/bin/bash
im1_dir=(~/prev1/*.png) 
im2_dir=(~/prev3/*.png)

for ((i = 0, j = 0,
          n1 = ${#im1_dir[@]}, 
          n2 = ${#im2_dir[@]}, 
          s = n1 >= n2 ? n1 : n2, 
          is = 0, js = 0; 

      is < s && js < s; 

      i++, is = i, i %= n1, 
          j++, js = j, j %= n2))
do
    run_black "${im1_dir[i]}" "${im2_dir[i]}"
done
Run Code Online (Sandbox Code Playgroud)

此版本仅为内部循环(第二个目录)使用数组.它只会执行与第一个目录中的文件一样多的次数.

#!/bin/bash
im1_dir=~/prev1/*.png
im2_dir=(~/prev3/*.png)

for file1 in $im1_dir
do
    run_black "$file1" "${im2_dir[i++]}"
done
Run Code Online (Sandbox Code Playgroud)