我试图将结果保存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
这是用于将输出结果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因此不能保证数组的元素就是您想要的。
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。