所以,我正在构建一个bash脚本,它遍历从1到9的数字命名的文件夹。脚本依赖于通过用户输入获取文件夹名称。我的目的是使用for loop
使用read
输入来获取文件夹名称或一系列文件夹名称,然后执行一些操作。
示例:
我们假设我想使用特定范围的文件夹rsync -a
进行备份。通常我会这样做:
for p in {1..7}; do
rsync -a $p/* backup.$p
done
上面将递归备份目录1 2 3 4 5 6和7中的所有内容,并将它们放入名为' backup。{index-number}'的文件夹中。它不会捕获带有前导.
的文件夹/文件,但现在这并不重要。
现在我在交互式bash脚本中有一个类似的循环。我正在使用select
和case
语句执行此任务。 case
中的一个选项是这个循环,它应该以某种方式从用户输入获得一系列数字。这现在成了一个问题。
问题:
如果我使用read
来获取范围,那么在使用{1..7}
作为输入时它会失败。输入是按字面意思输出的,输出只是:
{1..7}
我真的很想知道为什么会这样。让我使用简单的echo
命令来使用更具描述性的示例。
var={1..7} # fails and just outputs {1..7}
for p in $var; do echo $p;done
read var # Same result as above. Just outputs {1..7}
for p in $var; do echo $p;done
for p in {1..7}; do echo $p;done # works fine and outputs the numbers 1-7 seperated with a newline.
我通过将数字存储在数组中找到了解决方法。然后,用户可以输入由空格字符分隔的文件夹名称,如下所示:1 2 3 4 5 6 7
read -a var # In this case the output is similar to the 3rd loop above
for p in ${var[@]}; do echo $p; done
这可能是一种方法但是当备份40个文件夹(1-40)时,然后逐个添加所有数字会使我的脚本变得多余。人们可以在同一时间找到解决千年问题之一的办法。
有没有办法read
一系列数字,如{1..9},或者是否有另一种方式可以从终端输入到脚本中,这样我就可以在一个范围内迭代for-loop
吗
这听起来像谷歌的问题,但我显然使用错误的模式来获得有用的答案。 SO上大多数类似的问题都涉及支撑和参数扩展问题,但这并不是我遇到的问题。然而,对我来说,感觉这个问题的答案正朝着类似的方向发展。我无法理解为什么for-loop
为{1..7}
分配var={1..7}
有效,但$ echo $BASH_VERSION
4.2.25(1)-release
做同样的事情。 Plz help -.-
编辑:我的bash版本:
select when_created, status
from tablea
when_created Status
1/1/2015 ACTIVE
3/1/2015 ACTIVE
4/1/2015 INACTIVE
4/6/2015 INACTIVE
6/7/2015 ACTIVE
10/9/2015 INACTIVE
EDIT2:支架扩展的多功能性对我来说非常重要。可能的解决方案应该包括定义尽可能多的范围的能力。就像我希望能够选择只备份1个文件夹或f.ex 4-22之间的固定范围,甚至多个选项,如文件夹1,2,5,6-7
答案 0 :(得分:1)
不在变量的右侧或参数扩展上执行括号扩展。使用C风格的循环,用户在必要时输入范围的上端。
read upper
for ((i=1; i<=$upper; i++)); do
输入由空格分隔的下限和上限
read lower upper
for (i=$lower; i <= $upper; i++)); do
对于任意一组值,只需将负担推给用户以生成适当的列表;不要尝试实现自己的解析器来处理1,2,20-22
:
while read p; do
rsync -a $p/* backup.$p
done
输入是每行一个值,例如
1
2
20
21
22
即使用户正在使用shell,他们也可以使用类似
的方式调用脚本printf '%s\n' 1 2 20..22 | backup.sh
用户生成列表比安全解析描述列表的字符串更容易。
答案 1 :(得分:-1)
邪恶的eval
$ var={1..7}
$ for i in $(eval echo $var); do echo $i; done
这也有效,
$ var="1 2 {5..9}"
$ for i in $(eval echo $var); do echo $i; done
1
2
5
6
7
8
9
恶魔eval是一个笑话,也就是说,只要你知道你正在评估什么。
或者,awk
$ echo "1 2 5-9 22-25" |
awk -v RS=' ' '/-/{split($0,a,"-"); while(a[1]<=a[2]) print a[1]++; next}1'
1
2
5
6
7
8
9
22
23
24
25