我在目录中有一些文件:touch dir1/dir2/bad\ name{1..4}
。我想将这些文件(bad name1 - bad name4
)从移动dir2
到dir1
,并立即重命名它们。由于这些文件的名称不正确,我将简单地将它们视为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 expansion
(GNU 括号扩展)。这可能吗,或者括号不能在一次迭代中在 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
是为了获取字符串中从零开始的索引......$step
replacements
是我们从绳子上剪下的每一段的长度
限制:
- 此代码假设我们想要从 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}
循环中。