我正在尝试在 bash 中构建一个基本的 REPL。该脚本动态填充目录中的文件列表以供用户运行。
文件空间:
|
|\ scripts/
|| script1.sh
|| script2.sh
|
\ shell/
| shell.bashrc
| shell.desktop
从 shell.bashrc 中,我使用以下命令来获取文件名数组:
readarray -d " " filenames < <(find ../bin -type f -executable)
filenames
我可以很好地打印该数组,并且它包含一个空格分隔的字符串,该字符串"script1.sh script2.sh"
按预期保存。
但是当我尝试访问数组的第一个元素时,echo ${filenames[0]}
它会打印每个元素。除 0 之外的任何其他索引都会返回空字符串。
我的bash版本是5.0.17,文件的第一行是#!/bin/bash
在尝试以下方法得到类似的结果后,我转而使用“readarray”:
filenames=($(find "../bin" -type f -executable))
编辑:找到了一个愚蠢的解决方法,并且仍然想知道原始帖子哪里出了问题。解决方法:
readarray -d " " filenames < <(find ../bin -type f -executable)
arr=($filenames)
echo ${arr[1]}
它按预期打印数组的第 6 个元素。
答案1
默认情况下,find
输出结果以换行符分隔。通过-d " "
在 mapfile/readarray 命令中进行设置,您会导致(假设没有任何名称)包含空格字符)所有结果连接成一个字符串 - 换行符等。当你然后echo ${filenames[0]}
(与未引用的变量扩展${filenames[0]}
和默认的 space-tab-newline 值IFS
),shell 在换行符上拆分,并使用空格1echo
重新组合结果。
而是使用
readarray -t filenames < <(find ../bin -type f -executable)
它将把输入解析为换行符分隔的数据,但从存储的元素中去除尾随换行符。或者 - 更好 - 如果你的 bash 版本支持它,
readarray -t -d '' filenames < <(find ../bin -type f -executable -print0)
它使用空字节而不是换行符(使所有合法文件名都安全,甚至包含换行符的文件名)。
1参见什么时候需要双引号?