开发者社区> 问答> 正文

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

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

#!/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文件。所以我期望'2'作为的结果${len}。但是,它打印1。原因是它将所有结果都find作为一个元素。我怎样才能解决这个问题?

PS 我发现了几个解决方案,在计算器上有关类似问题。但是,它们有些不同,因此我无法申请。我需要在循环之前将结果存储在变量中。再次感谢。 问题来源于stack overflow

展开
收起
保持可爱mmm 2020-02-09 11:58:32 2448 0
1 条回答
写回答
取消 提交回答
  • 这是用于将输出结果find放入bash数组的一种解决方案:

    array=() while IFS= read -r -d $'\0'; do array+=("$REPLY") done < <(find . -name "${input}" -print0) 这很棘手,因为通常文件名可以包含空格,换行符和其他对脚本不利的字符。使用find并使文件名安全地分开的唯一方法是使用,该命令-print0将打印以空字符分隔的文件名。如果bash的readarray/ mapfile函数支持以空分隔的字符串,但不支持,则不会带来太大的麻烦。Bash的做法read使我们进入了上面的循环。

    [此答案最初写于2014年。如果您使用的是最新版本的bash,请参见下面的更新。]

    怎么运行的 第一行创建一个空数组: array=()

    每次read执行该语句时,都会从标准输入中读取以空分隔的文件名。该-r选项告诉read您保留反斜杠字符。该-d $'\0'告诉read输入将以空分隔。由于我们省略了名称read,因此shell将输入内容放入默认名称:中REPLY。

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

    最后一行结合了重定向和命令替换,以将输出提供find给while循环的标准输入。

    为什么要使用流程替代? 如果我们不使用流程替换,则循环可以写成:

    array=() find . -name "${input}" -print0 >tmpfile while IFS= read -r -d $'\0'; do array+=("$REPLY") done <tmpfile rm -f tmpfile 上面的输出find存储在一个临时文件中,该文件用作while循环的标准输入。进程替换的想法是使此类临时文件变得不必要。因此,与其让while循环从其获取标准输入tmpfile,不如让循环从其获取标准输入<(find . -name ${input} -print0)。

    流程替换非常有用。在许多要从文件中读取命令的地方,可以指定进程替代<(...),而不是文件名。有一个类似的形式,>(...)可以用来代替命令要写入文件的文件名。

    像数组一样,进程替换是bash和其他高级shell的功能。它不是POSIX标准的一部分。

    另类:lastpipe 如果需要,lastpipe可以使用它代替进程替换(提示:Caesar):

    set +m shopt -s lastpipe array=() find . -name "${input}" -print0 | while IFS= read -r -d $'\0'; do array+=("$REPLY"); done; declare -p array shopt -s lastpipe告诉bash在当前shell(而不是后台)中的管道中运行最后一个命令。这样,array流水线完成后便仍然存在。因为lastpipe仅在关闭作业控制后才会生效,所以我们运行set +m。(在脚本中,相对于命令行,默认情况下,作业控制处于关闭状态。)

    补充说明 以下命令创建一个shell变量,而不是一个shell数组:

    array=find . -name "${input}" 如果要创建一个数组,则需要将括号放在find的输出周围。因此,天真的,一个人可以:

    array=(find . -name "${input}") # don't do this 问题在于外壳程序对的结果执行单词拆分,find因此不能保证数组的元素就是您想要的。

    2020-02-09 11:58:50
    赞同 展开评论 打赏
问答分类:
问答地址:
问答排行榜
最热
最新

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载