我可以在 for 循环中使用 bash 括号扩展吗?

我可以在 for 循环中使用 bash 括号扩展吗?

我在目录中有一些文件:touch dir1/dir2/bad\ name{1..4}。我想将这些文件(bad name1 - bad name4)从移动dir2dir1,并立即重命名它们。由于这些文件的名称不正确,我将简单地将它们视为ls bad*。现在,要根据需要移动它们,我会尝试for i in $(ls *bad); do mv $i ../anothername{a..d}; done。我试图解决的问题是如何进行一对一映射(循环和扩展之间) - 即

对于 for 循环的一次迭代,进行一次括号扩展

bad\ name故意放了,因为我可以做mv bad\ name{1..4} ../anothername{a..d},因此不需要for loop,因此不是问题,但我想用file expansion *-来获取这些文件ls bad*并将它们映射到 for 循环中brace expansionGNU 括号扩展)。这可能吗,或者括号不能在一次迭代中在 for 循环中展开?因此唯一的选择是在 mv 的两边都使用括号(如mv bad\ name{1..4} ../anothername{a..d}

答案1

我认为,鉴于该工具 (Bash),没有哪个解决方案会真正简单易懂,尤其是可读性。正如您的问题评论中所述,您还可以设计一种仅使用字符串(无数组)的方法。但是,数组的优点是允许替换不同长度。

无论如何,这是我的例子(这echo是故意的,所以如果有人粘贴并执行脚本,这不会立即开始其业务):

#!/usr/bin/env bash
replacements="aabbccdd"
let step=2
let max=$((${#replacements}/step))
for ((i=1;i<=$max;i++)); do
    echo mv bad\ name$i ../anothername${replacements:$((i*step-step)):$step}
done

解释:

(经测试发现可与 Bash 4.4.20 配合使用)

  • step设置为一个单独替换的长度
  • replacements拿着一根绳子,我们可以从中剪下长度step
  • C 风格的 for 循环仅用i作数字索引变量
  • ${replacements:...:...}进行单独替换
    • $((i*step-step))是一个算术表达式,该表达式正是它看起来的样子:i*step-step...-step是为了获取字符串中从零开始的索引......
    • $stepreplacements是我们从绳子上剪下的每一段的长度

限制:

  • 此代码假设我们想要从 1 开始,然后连续上升到给定的最大值,当然这个最大值是可以调整的
  • 该代码不再使用括号扩展,尽管可以通过eval... 来完成,但它不会提高可读性...
  • 此代码要求替换的长度统一(另一个提出的使用数组的解决方案没有这个限制!)

答案2

准备两个数组:

src=( bad\ name{1..4} )
dst=( anothername{a..d} )

确认每个元素都有 4 个:

echo "${#src[@]}"
echo "${#dst[@]}"

然后在dir2

for i in {0..3}; do mv "${src[i]}" "../${dst[i]}"; done

索引数组是从 索引的0,这就是为什么{0..3}不在{1..4}循环中。

相关内容