使用Bash列出来自for循环前缀的所有文件

时间:2014-03-12 22:50:33

标签: bash directory-listing

这是我的bash脚本的一个小但[完整]部分,如果从存储的数组中获取前缀,它将查找并输出mydir中的所有文件。我注意到的奇怪的是,如果我从脚本中取出“-maxdepth 1 -name”,这个脚本就可以正常运行,否则它只会给我带有数组中第一个元素前缀的文件。

如果有人向我解释这一点会很有帮助。提前抱歉,如果有一些事我看起来很傻。我对脚本编程比较陌生。

#!/bin/sh
DIS_ARRAY=(A B C D)
echo "Array is : "
echo ${DIS_ARRAY[*]}
for dis in $DIS_ARRAY
do
    IN_FILES=`find /mydir  -maxdepth 1 -name "$dis*.xml"`
    for file in $IN_FILES
    do
    echo $file
    done
done

输出:

/mydir/Abc.xml
/mydir/Ab.xml
/mydir/Ac.xml

预期产出:

/mydir/Abc.xml
/mydir/Ab.xml
/mydir/Ac.xml
/mydir/Bc.xml
/mydir/Cb.xml
/mydir/Dc.xml

2 个答案:

答案 0 :(得分:2)

循环被打破了。

之所以如此
IN_FILES=`find mydir  -maxdepth 1 -name "$dis*.xml"`

有效,而

IN_FILES=`find mydir "$dis*.xml"`

不是因为在第一个中,您指定了-name。在第二个中,find列出了mydir中的所有文件。如果您将第二个更改为

IN_FILES=`find mydir -name "$dis*.xml"`

你会看到循环不起作用。

正如评论中所提到的,您当前使用的语法$DIS_ARRAY只会为您提供数组的第一个元素。

尝试将循环更改为:

for dis in "${DIS_ARRAY[@]}"

在这种情况下,周围的双引号不是必需的,所以你可以这样做:

for dis in ${DIS_ARRAY[@]}

如果数组包含空格,则需要引号,例如,如果要循环遍历数组arr=( "a a" "b b" )

这是一个测试,显示正在发生的事情:

#!/bin/sh

arr=("a a" "b b")

echo using '$arr'
for i in $arr; do echo $i; done
echo using '${arr[@]}'
for i in ${arr[@]}; do echo $i; done
echo using '"${arr[@]}"'
for i in "${arr[@]}"; do echo $i; done

输出:

using $arr
a
a
using ${arr[@]}
a
a
b
b
using "${arr[@]}"
a a
b b

有关详细信息,请参阅此related question

答案 1 :(得分:2)

@ TomFenech的回答解决了您的问题,但让我建议其他改进:

#!/usr/bin/env bash

DIS_ARRAY=(A B C D)
echo "Array is : "
echo ${DIS_ARRAY[*]}
for dis in "${DIS_ARRAY[@]}"
do
    for file in "/mydir/$dis"*.xml
    do
        if [ -f "$file" ]; then
            echo "$file"
        fi
    done
done
  • 您的shebang系列引用sh,但您的问题已标记为bash - 除非您需要POSIX合规性,否则请使用bash shebang行来充分利用所有bash必须提供
  • 要匹配给定目录中直接的文件(即,如果您不需要遍历整个子树),请使用glob(文件名模式)并依赖于上面代码中的路径名扩展 - 不需要find和命令替换。
  • 请注意通配符char。不引用*以确保路径名扩展。
  • 警告:如果找不到匹配的文件,则保持glob不受影响(假设nullglob shell选项为OFF,默认情况下为OFF),因此循环输入一次,文件名无效(未扩展的glob) - 因此[ -f "$file" ]有条件确保找到实际的匹配(作为旁白:使用bashisms,你可以使用[[ -f $file ]]代替。)