Jun*_* Oh 62 arrays variables 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
Run Code Online (Sandbox Code Playgroud)
我在当前目录下获得了2个.txt文件.所以我期待'2'作为结果find.然而,它打印1.原因是它将查找的所有结果作为一个元素.我怎样才能解决这个问题?谢谢.
PS我在Stack OverFlow中找到了几个关于类似问题的解决方案.但是,它有点不同所以我可以申请我的.我需要在循环之前将结果存储到变量.再次感谢.
Joh*_*024 97
下面是用于获取的输出的一个溶液find到一个bash数组:
array=()
while IFS= read -r -d $'\0'; do
array+=("$REPLY")
done < <(find . -name "${input}" -print0)
Run Code Online (Sandbox Code Playgroud)
这很棘手,因为通常,文件名可以包含空格,换行符和其他脚本恶意字符.使用find和使文件名彼此安全分离的唯一方法是使用-print0打印用空字符分隔的文件名.如果bash的readarray/ mapfile函数支持以空值分隔的字符串但它们不支持,那么这不会带来太多麻烦.Bash read的确如此,这导致我们进入上面的循环.
第一行创建一个空数组: 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
Run Code Online (Sandbox Code Playgroud)
在上面,输出find存储在临时文件中,该文件用作while循环的标准输入.进程替换的想法是不需要这样的临时文件.所以,不是让while循环得到它的标准输入tmpfile,我们可以让它得到它的标准输入<(find . -name ${input} -print0).
过程替换非常有用.在命令要从文件中读取的许多位置,您可以指定进程替换<(...),而不是文件名.有一种类似的形式,>(...)可用于代替命令要写入文件的文件名.
与数组一样,进程替换是bash和其他高级shell的一个特性.它不是POSIX标准的一部分.
以下命令创建shell变量,而不是shell数组:
array=`find . -name "${input}"`
Run Code Online (Sandbox Code Playgroud)
如果要创建数组,则需要在find的输出周围放置parens.所以天真地,人们可以:
array=(`find . -name "${input}"`) # don't do this
Run Code Online (Sandbox Code Playgroud)
问题是shell对结果执行了单词拆分,find因此不保证数组的元素是你想要的.
che*_*ner 15
如果您使用bash4或更高版本,您可以取代你使用的find有
shopt -s globstar nullglob
array=( **/*"$input"* )
Run Code Online (Sandbox Code Playgroud)
匹配0或更多目录**启用的模式globstar,允许模式匹配当前目录中的任意深度.如果没有该nullglob选项,模式(在参数扩展之后)将按字面处理,因此如果没有匹配,您将拥有一个包含单个字符串而不是空数组的数组.
dotglob如果您想要遍历隐藏目录(例如.ssh)并匹配隐藏文件(例如.bashrc),也可以将选项添加到第一行.
Ben*_* W. 14
Bash 4.4 -d为readarray/ 引入了一个选项mapfile,因此现在可以通过以下方式解决
readarray -d '' array < <(find . -name "$input" -print0)
Run Code Online (Sandbox Code Playgroud)
一种适用于任意文件名(包括空格,换行符和通配符)的方法。
从手册中(省略其他选项):
Run Code Online (Sandbox Code Playgroud)mapfile [-d delim] [array]
-d
的第一个字符delim用于终止每个输入行,而不是换行符。如果delim为空字符串,mapfile则在读取NUL字符时将终止一行。
并且readarray只是的同义词mapfile。
sun*_*sen 12
以下似乎适用于 macOS 上的 Bash 和 Z Shell。
#! /bin/sh
IFS=$'\n'
paths=($(find . -name "foo"))
unset IFS
printf "%s\n" "${paths[@]}"
Run Code Online (Sandbox Code Playgroud)
你可以试试像
array=(`find . -type f | sort -r | head -2`) ,为了打印数组值,你可以尝试像echo这样的东西 "${array[*]}"
| 归档时间: |
|
| 查看次数: |
63928 次 |
| 最近记录: |