今天我在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
似乎在第一个脚本中,只有一个循环,所有文件名都存储在FIRST循环中的变量$ file中,用空格分隔。但是在第二个脚本中,一个文件名只在一个循环中存储在$ file中,并且有多个循环。这两个脚本之间究竟有什么区别?
非常感谢,也许我的问题有点天真......
答案 0 :(得分: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"*
但它很脆弱;例如,当您忘记在变量/
的末尾添加$InputDir
时,它将失败。
for file in "$InputDir"/*
稍微好一点(Unix会忽略路径中的双斜线)但是当$InputDir
未设置或为空时它会导致麻烦:你会突然列出/
(root)中的文件)文件夹。例如,由于输入错误,可能会发生这种情况:
inputDir=...
for file in "$InputDir"/*
Unix上的案例: - )
为了帮助您理解这样的代码,请在要调试的代码之前的行中使用set -x
(“启用跟踪”)。
答案 1 :(得分: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/*