我的目录包含以下文件:
FILE1_h0_something_1950_other.gz
FILE2_h0_something_1950_other.gz
FILE3_h0_something_1950_other.gz
这里是我的bash脚本的一部分:
year=1950
for nc_gz in "$input_path/*h3*$year*.gz"; do
gunzip $nc_gz
done
我注意到有时候(奇怪的行为。。。我除了总是或从不)一个名为*h3*1950*的文件是在我的目录中创建的。
当目录不包含gz文件时,代码失败。
问题在哪里?
谢谢
最佳答案
for nc_gz in "$input_path/*h3*$year*.gz"; do
您正在迭代一个元素的列表。因为
"$input_path/*h3*$year*.gz"
是双引号,所以它是一个字符串。因此,如果input_path
的值是/some/where
,而year
的值是2017
,那么这将运行循环体一次,并将nc_gz
设置为/some/where/*h3*2017*.gz
。 gunzip $nc_gz
这里
$nc_gz
没有被引用,所以这将split+glob operator应用于结果。在上面的例子中,/some/where/*h3*2017*.gz
被扩展到匹配文件的列表;除非没有匹配的文件,否则这将使用参数gunzip
调用/some/where/*h3*2017*.gz
。首先,正确引用:
Use double quotes around variable substitutions。
不要在通配符周围使用双引号。
for nc_gz in "$input_path/"*h3*"$year"*.gz; do gunzip "$nc_gz" done
This still runs the loop once if the wildcard does not match any files, because of a shell misfeature that non-matching wildcard patterns are left unchanged instead of being expanded to an empty list. In bash (but not in plain sh), you can avoid this by setting the nullglob
option.
#!/bin/bash
shopt -o nullglob
for nc_gz in "$input_path/"*h3*"$year"*.gz; do
gunzip "$nc_gz"
done
在普通SH中,可以通过跳过不存在的文件来避免这种情况。
for nc_gz in "$input_path/"*h3*"$year"*.gz; do
if [ ! -e "$nc_gz" ]; then continue; fi
gunzip "$nc_gz"
done
注意,我假设这是一个简化的代码,除了调用
gunzip
之外,您还需要循环来执行其他操作。如果您只需要解压缩文件,那么您可以一次调用gunzip
,因为它支持多个文件参数。gunzip "$input_path/"*h3*"$year"*.gz
这是在解压缩文件的意义上工作的,如果通配符模式与任何文件不匹配,它不会做任何事情,但是GunZip将抱怨不存在的文件。这里bash的
nullglob
选项对您没有帮助,因为调用没有文件名的gunzip
也不起作用(它希望从标准输入中解压缩数据)。您需要测试匹配文件的数量。unzip_matching_files () {
if [ $# -eq 1 ] && [ ! -e "$1" ]; then return; fi
gunzip "$@"
}
unzip_matching_files "$input_path/"*h3*"$year"*.gz
关于bash - BASH-使用LS和通配符的FOR循环,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49382814/