BASH - 使用LS和通配符的FOR循环

时间:2018-03-20 11:17:28

标签: bash wildcard

我的目录包含以下文件:

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文件时代码失败。

问题出在哪里?

由于

2 个答案:

答案 0 :(得分:4)

for nc_gz in "$input_path/*h3*$year*.gz"; do

您正在迭代一个元素的列表。由于"$input_path/*h3*$year*.gz"是双引号,因此它是一个字符串。因此,如果input_path的值为/some/whereyear的值为2017,那么这将运行循环体一次,nc_gz设置为{{1} }}

/some/where/*h3*2017*.gz

此处 gunzip $nc_gz 未加引号,因此这会将split+glob operator应用于结果。在上面的示例中,$nc_gz扩展为匹配文件列表;除非没有匹配的文件,否则会使用参数/some/where/*h3*2017*.gz调用gunzip

首先,正确引用:

for nc_gz in "$input_path/"*h3*"$year"*.gz; do
      gunzip "$nc_gz"
done

如果通配符与任何文件都不匹配,这仍然会运行一次循环,因为shell不匹配不匹配的通配符模式保持不变而不是扩展为空列表。在bash中(但不是简单的sh),您可以通过设置/some/where/*h3*2017*.gz选项来避免这种情况。

nullglob

简单来说,你可以通过跳过不存在的文件来避免这种情况。

#!/bin/bash
shopt -o nullglob
for nc_gz in "$input_path/"*h3*"$year"*.gz; do
  gunzip "$nc_gz"
done

请注意,我认为这是简化代码,除了调用for nc_gz in "$input_path/"*h3*"$year"*.gz; do if [ ! -e "$nc_gz" ]; then continue; fi gunzip "$nc_gz" done 之外,您还需要循环来执行其他操作。如果您只需要解压缩文件,那么您可以一次调用gunzip,因为它支持多个文件参数。

gunzip

这在解压缩文件的意义上是有效的,如果通配符模式与任何文件都不匹配,它就什么都不做,但是gunzip会抱怨不存在的文件。 bash的gunzip "$input_path/"*h3*"$year"*.gz 选项无法帮助您,因为在没有文件名的情况下调用nullglob也不起作用(它希望从标准输入中解压缩数据)。您需要测试匹配文件的数量。

gunzip

答案 1 :(得分:0)

也许是这样吗?

for i in $(find ../path1 path2 path3 -name "*.env" 2>/dev/null); do
    echo $i
done

忽略2> / dev / null的错误,否则将打印path1不存在

find: ‘../path1’: No such file or directory