如何将"find"命令结果存储为Bash中的数组

2023-12-11 13:09:31 浏览数 (1)

更多好文请关注↑

问:

我正在尝试将 find 的结果保存为数组。这是我的代码:

代码语言:javascript复制
#!/bin/bash

echo "input : "
read input

echo "searching file with this pattern '${input}' under present directory"
array=`find . -name ${input}`

len=${#array[*]}
echo "found : ${len}"

i=0

while [ $i -lt $len ]
do
echo ${array[$i]}
let i  
done

我在当前目录下获得了 2 个 .txt 文件。所以我期望 ${len} 的结果为 '2'。然而,它打印的是 '1'。原因是它将 find 命令的所有结果视为一个元素。我该如何修复这个问题?

答:

如果你有最新的bash版本(4.4-alpha或更高),建议使用 bash 内置的 readarray 命令。

代码语言:javascript复制
readarray -d '' array < <(find . -name "$input" -print0)

可以处理任意文件名(包括空格、换行符和通配符)。这要求你的 find 支持 -print0,例如 GNU find 就支持。

由于 readarray 同 mapfile,可以使用 help mapfile 命令查看帮助文档。

从标准输入读取行到索引数组变量中。 选项说明: -d delim 使用 <delim> 而非换行符标志一行的结束 -n count 最多复制 <count> 行。如果 <count> 为 0,则复制所有行 -O origin 从索引 <origin> 开始赋值给 <数组> 变量。默认索引是 0 -s count 丢弃最初读取的 <count> 行 -t 从读取的每行末尾删除一个 <分隔符>(默认为换行符) -u fd 从文件描述符 <FD> 中读取行,而不是标准输入 -C callback 每读取 <间隔> 行之后对 <callback> 进行求值 -c quantum 指定每次调用 <callback> 之前读取的行数,如果使用了 -C 而没有 -c,默认的 quantum 是 5000

如果没有新版本的 bash,可以使用如下办法:

代码语言:javascript复制
array=()
while IFS=  read -r -d $''; do
    array =("$REPLY")
done < <(find . -name "${input}" -print0)

测试截图如下:

我们解读一下代码,

1. 语句 array=() 创建了一个空数组;

2. 每次执行 read 语句时,都会从标准输入中读取以 null 分隔的文件名。-r 选项告诉 read 不要处理反斜线字符。-d $'' 告诉 read 输入将以 null 分隔。由于我们省略了要读取的名称,shell 将输入放入默认名称:REPLY。

3. 语句 array =("$REPLY") 将新文件名附加到数组 array 中。

4. 最后一行结合了重定向和命令替换,将 find 的输出提供给 while 循环的标准输入。其中 -print0 的作用是让 find 将当前文件的路径名打印到标准输出,后面跟一个 ASCII NUL 字符。


参考文档:

  • stackoverflow question 23356779
  • man bash
  • man find

相关阅读:

  • 如何批量删除名字乱码的空白文件
  • 如何通过一个Bash定界符来分割一个字符串
  • 如何将Bash数组的元素连接为分隔符分隔的字符串
  • 如何在Bash中连接字符串变量

更多好文请关注↓

0 人点赞