为了账号安全,请及时绑定邮箱和手机立即绑定

linux for循环

linux for循环

qq_爱上你_0 2017-05-13 16:17:13
cd /root/testfor i in $(ls *.tar.gz *.gz)       do           tar -zxf $i      done为什么(ls *.tar.gz *.gz)前面要加$,不加行不行
查看完整描述

2 回答

?
onemoo

TA贡献883条经验 获得超454个赞

for 语句中的 in 后面的内容就是需要被循环的哪些项。 比如 for i in A B C 在循环时,i 就分别是 A、B、C 这三个单词。

你理解这个 for 循环里的 i 是要在哪些项里循环吗?


你的例子中这些项就是 $(ls *.tar.gz *.gz) 这个东西。

先不管 $(),单看 ls *.tar.gz *.gz,这是一个 ls 命令,会列出当前目录下所有的 .tar.gz .gz 结尾的文件。而所列出的这些文件名就是需要循环的项。

也就是说你想要的循环项不是“ls *.tar.gz *.gz”这三个字,而是这句 ls 命令的执行结果。

像这样,想要在 bash 脚本中得到一个命令的执行结果,叫做“命令替换”。它的语法就是用 $(  ) 把命令括起来,到脚本运行时这里就会替换为该命令的执行结果了。

所以你这里既然需要的是 ls 的执行结果,那就要写 $(ls *.tar.gz *.gz)。

既然 $(...) 是“命令替换”的语法格式,那当然不能去掉 $ 了。


多说一些:

如果去掉 $ 会怎么样呢?  只剩下 (ls *.tar.gz *.gz),这里出现小括号是不合法的,所以脚本在执行到这里时会直接报错。


再多说一些:

前面说 in 后面的这些“字”就是循环项。 其实呢,for 语句会尝试对这些“字”做“路径名展开”。“路径名展开”就是指展开那些路径通配符 * ? 什么的。

所以如果你在 in 后面直接写 *.tar.gz,这里会直接被替换为所有 *.tar.gz 结尾的文件名,这样你甚至不需要用 ls 命令来帮你列出它们。

所以这句你直接写成 for i in *.tar.gz *.gz 也是可以的。

但有一点:如果没能成功进行路径名展开(也就是说目录下没有这样的文件),那 *tar.gz(或 *.gz)还是会被当作一个单纯的字来用。


最后多说一点:

对于前面一人的回答。$ 放在变量名前才是“变量展开”。而这里根本就没有变量的事,这只是“命令替换”而已。

查看完整回答
反对 回复 2017-06-29
?
孤独的小猪

TA贡献232条经验 获得超302个赞

不加$符号当然不可以了,shell里面加$符号才知道这是变量,想得到返回值

查看完整回答
1 反对 回复 2017-06-27
  • 2 回答
  • 0 关注
  • 1985 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信