在bash脚本中由find返回的元素数

时间:2015-03-24 15:32:25

标签: bash

我有以下bash脚本:

#!/bin/bash

test=$(find . -name "*.cfg")
echo ${#test[@]}

输出只是1.但是,find返回8个元素,当在循环中使用时,它们的名称会正确显示:

for f in $(find . -name "*.cfg")
do
    echo $f
done

如何查看test数组的大小?谢谢!

4 个答案:

答案 0 :(得分:3)

find的输出存储到数组中的唯一安全方法是使用-print0扩展名,而不是POSIX(但GNU find支持它):

files=()
while IFS= read -r -d '' file; do
    files+=( "$file" )
done < <(
    find . -name '*.cfg' -print0
)
printf 'There are %d files found.\n' "${#files[@]}"

如果您只想要找到的文件数量,可以使用它(使用-printf,而不是POSIX但GNU支持):

xfiles=$(find . -name '*.cfg' -printf 'x')
printf 'There are %d files found.\n' "${#xfiles}"

或符合POSIX标准:

xfiles=$(find . -name '*.cfg' -exec printf "%.sx" {} +)
printf 'There are %d files found.\n' "${#xfiles}"

现在Bash≥4可以自行解决这个问题:

shopt -s globstar nullglob
files=( **/*.cfg )
printf 'There are %d files found.\n' "${#files[@]}"

(虽然它可能比find慢。)

答案 1 :(得分:2)

test是一个字符串(不是数组)。

你正在使用[@],它没有做任何有用的事情,并且正在为你破坏事物。放弃它。

您希望${#test}获取字符串的长度。如果你想要一个数组,你需要做不同的事情。

想要解析/阅读/ for - 循环/等。通过这种方式输出(对于“奇数”文件名来说是不安全的。)

有关安全执行此操作的方法,请参阅http://mywiki.wooledge.org/BashFAQ/001(具体请参阅有关-print0的部分)。

答案 2 :(得分:2)

由于您没有使用find的任何其他功能,我会使用glob来创建数组:

# Bash 4+
shopt -s globstar
test=( **/*.cfg )

globstar选项启用模式**,它匹配路径中的0个或更多目录。它允许与目录层次结构进行递归匹配,因此**/*.cfg将匹配./foo.cfg./bar/hello world.cfg等。每个匹配的文件,无论文件名中是否存在任何特殊字符,都将是作为单个数组条目处理。

如果您需要支持bash的旧版本,假设您的find版本支持-print0或类似内容,则可以使用更复杂的技术。

答案 3 :(得分:-1)

你必须先创建一个数组,试试这个:

test=($(find . -name "*.cfg"))
echo ${#test[@]}