2014-03-12 74 views
2

这里是我的bash脚本的一个小部分,但它是查找并输出mydir中的所有文件(如果从存储数组中有前缀的话)。我注意到奇怪的是,如果我从脚本中取出“-maxdepth 1 -name”,则该脚本完美地工作,否则它只会给我带有数组中第一个元素的前缀的文件。Bash找到:列出所有带有for循环前缀的文件

如果有人向我解释这将是很大的帮助。对不起,如果有一件事显然愚蠢,我在做。我对脚本相对来说比较陌生。

#!/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

的环路断开任一方式。为什么

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进一步的细节。

+0

工作,谢谢!您能否足够解释为什么以前的方法不适用于这种方法?或者它只是一个标准的语法? – Karen

+0

@Karen:引用一个不带下标'[@]'(或等效的[*]')的数组变量只返回* first *元素的值。 – mklement0

+0

@ mklement0谢谢,我已将您的意见加入 –

1

@ 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 
  • 你的家当行引用sh,但你的问题是标签bash - 除非你需要符合POSIX,使用bash家当line利用所有bash必须提供的优势
  • 匹配位于的文件直接在给定的目录中(即,如果您不需要遍历整个子树),使用glob(文件名模式)并依赖于上面的代码中的路径名扩展 - 不需要find和命令替换。
  • 请注意通配符字符。 *被UN引用来确保路径名扩展。
  • 注意:如果找不到匹配的文件,glob将保持不变(假设nullglob shell选项为OFF,默认情况下为OFF),因此循环只输入一次,使用无效文件名(未扩展的glob) - 因此[ -f "$file" ]有条件确保找到实际匹配(作为旁白:使用bashisms,您可以使用[[ -f $file ]]代替)。
+0

非常感谢。你的回答确实有帮助。 – Karen

+0

@Karen:很高兴听到它。 – mklement0