BASH数组中包含空格

我想在我的相机的文件名的bash-shell中构造一个数组:

FILES=(2011-09-04 21.43.02.jpg 2011-09-05 10.23.14.jpg 2011-09-09 12.31.16.jpg 2011-09-11 08.43.12.jpg) 

正如你所看到的,每个文件名的中间都有一个空格。
我已经尝试用引号将每个名字包装起来,并用反斜杠将空间转义出来,两者都不起作用。

当我尝试访问数组元素时,它将继续将空间视为元素分隔符。

我怎样才能正确捕捉名称内的空间的文件名?

我认为这个问题可能部分与你如何访问元素有关。 如果我for elem in $FILES做一个简单for elem in $FILES ,我遇到同样的问题。 但是,如果我通过它的索引访问数组,如果这样,它可以工作,如果我用数字或转义添加元素:

 for ((i = 0; i < ${#FILES[@]}; i++)) do echo "${FILES[$i]}" done 

$FILES的这些声明中的任何一个都应该工作:

 FILES=(2011-09-04\ 21.43.02.jpg 2011-09-05\ 10.23.14.jpg 2011-09-09\ 12.31.16.jpg 2011-09-11\ 08.43.12.jpg) 

要么

 FILES=("2011-09-04 21.43.02.jpg" "2011-09-05 10.23.14.jpg" "2011-09-09 12.31.16.jpg" "2011-09-11 08.43.12.jpg") 

要么

 FILES[0]="2011-09-04 21.43.02.jpg" FILES[1]="2011-09-05 10.23.14.jpg" FILES[2]="2011-09-09 12.31.16.jpg" FILES[3]="2011-09-11 08.43.12.jpg" 

访问数组项目的方式肯定有问题。 这是如何完成的:

 for elem in "${files[@]}" ... 

从bash的manpage :

数组中的任何元素都可以使用$ {name [subscript]}引用。 …如果下标是@或*,则该单词扩展为名称的所有成员。 这些下标仅在双引号出现在单引号内时才有所不同。 如果单词是双引号, $ {name [*]}将扩展为单个单词,每个数组成员的值由IFS特殊variables的第一个字符分隔, $ {name [@]}将名字到一个单独的词

当然,访问单个成员时也应该使用双引号

 cp "${files[0]}" /tmp 

您需要使用IFS以空格作为元素分隔符。

 FILES=("2011-09-04 21.43.02.jpg" "2011-09-05 10.23.14.jpg" "2011-09-09 12.31.16.jpg" "2011-09-11 08.43.12.jpg") IFS="" for jpg in ${FILES[*]} do echo "${jpg}" done 

如果你想分开的基础上。 那么只要做IFS =“。” 希望它可以帮助你:)

我同意其他人的看法,那就是如何访问这些问题。 引用数组赋值中的文件名是正确的:

 FILES=( "2011-09-04 21.43.02.jpg" "2011-09-05 10.23.14.jpg" "2011-09-09 12.31.16.jpg" "2011-09-11 08.43.12.jpg" ) for f in "${FILES[@]}" do echo "$f" done 

在任何forms的"${FILES[@]}"数组周围使用双引号将数组分割成每个数组元素的一个字。 除此之外,它不会做任何分词。

使用"${FILES[*]}"也有一个特殊的含义,但它将数组元素与$ IFS的第一个字符连接起来,产生一个单词,这可能不是你想要的。

使用裸${array[@]}${array[*]}会将扩展的结果进一步分词,所以最终会以空格(以及$IFS其他任何内容)每个数组元素的一个单词。

使用C风格for循环也很好,并避免担心分词,如果你不清楚:

 for (( i = 0; i < ${#FILES[@]}; i++ )) do echo "${FILES[$i]}" done 

逃逸作品

 #!/bin/bash FILES=(2011-09-04\ 21.43.02.jpg 2011-09-05\ 10.23.14.jpg 2011-09-09\ 12.31.16.jpg 2011-09-11\ 08.43.12.jpg) echo ${FILES[0]} echo ${FILES[1]} echo ${FILES[2]} echo ${FILES[3]} 

输出:

 $ ./test.sh 2011-09-04 21.43.02.jpg 2011-09-05 10.23.14.jpg 2011-09-09 12.31.16.jpg 2011-09-11 08.43.12.jpg 

引用string也会产生相同的输出。

不完全是对原始问题的引用/转义问题的一个答案,但可能对于op来说实际上更有用:

 unset FILES for f in 2011-*.jpg; do FILES+=("$f"); done echo "${FILES[@]}" 

当然,expression必须被采纳到特定的要求(例如, *.jpg为全部或2001-09-11*.jpg仅为某一天的图片)。

另一种解决scheme是使用“while”循环代替“for”循环:

 index=0 while [ ${index} -lt ${#Array[@]} ] do echo ${Array[${index}]} index=$(( $index + 1 )) done