4

今天我在linux中尝试了一个脚本来获取一个目录中的所有文件。这很简单,但我发现了一些有趣的东西。

 #!/bin/bash
InputDir=/home/XXX/
for file in $InputDir'*'
do
  echo $file
done

输出是:

/home/XXX/fileA /home/XXX/fileB 

但是当我直接输入目录时,比如:

 #!/bin/bash
InputDir=/home/XXX/
for file in /home/XXX/*
do
  echo $file
done

输出是:

/home/XXX/fileA
/home/XXX/fileB

似乎,在第一个脚本中,只有一个循环,所有文件名都存储在第一个循环中的变量 $file 中,用空格分隔。但是在第二个脚本中,一个文件名仅在一个循环中存储在 $file 中,并且循环不止一个。这两个脚本之间到底有什么区别?

非常感谢,也许我的问题有点天真..

4

2 回答 2

8

行为是正确的并且“符合预期”。

for file in $InputDir'*'意思是assign "/home/XXX/*" to $file(注意引号)。由于您引用了星号,因此此时不会执行。当 shell 看到echo $file时,它首先扩展变量,然后进行全局扩展。所以在第一步之后,它看到

echo /home/XXX/*

在全局扩展之后,它看到:

echo /home/XXX/fileA /home/XXX/fileB

只有现在,它才会执行命令。

在第二种情况下,模式在执行/home/XXX/*之前被扩展for,因此,目录中的每个文件都被分配给file然后执行循环体。

这将起作用:

for file in "$InputDir"*

但它很脆;/例如,当您忘记将 a 添加到变量的末尾时,它将失败$InputDir

for file in "$InputDir"/*

稍微好一点(Unix 将忽略路径中的双斜杠),但如果$InputDir未设置或为空,则会导致麻烦:您会突然列出/(根)文件夹中的文件。例如,由于拼写错误,可能会发生这种情况:

inputDir=...
for file in "$InputDir"/*

Unix 上的案例很重要 :-)

为了帮助您理解这样set -x的代码,请在要调试的代码之前的一行中使用 ("enable tracking")。

于 2013-04-18T11:59:06.523 回答
6

不同之处在于引用'*'。在第一种情况下,循环只执行一次,当传递给时,$file等于/home/XXX/*然后扩展到目录中的所有文件echo。在第二种情况下,它每个文件执行一次,$file依次等于每个文件名。

底线 - 改变:

for file in $InputDir'*'

至:

for file in $InputDir*

或者,更好,并使其更具可读性 - 更改:

InputDir=/home/XXX/
for file in $InputDir'*'

至:

InputDir=/home/XXX
for file in $InputDir/*
于 2013-04-18T11:56:47.803 回答