如何在Shell脚本中将指定目录的文件存入Bash数组?
嗨,这个问题我太熟了!咱们先把事儿说清楚:arr=( path-to-dir/* )其实就是最优方案,你觉得它没生效大概率是碰到了几个常见的小坑,而不是这个方法本身有问题~
为什么你觉得arr=( path-to-dir/* )没生效?
最常见的两个原因:
- 目标目录是空的:默认情况下,Bash如果用
*匹配不到任何文件,会把path-to-dir/*作为一个字符串直接塞进数组里,这时候数组里只有这一个无效元素。解决方法是开启nullglob选项,让空匹配时直接返回空数组:# 开启nullglob(临时生效,只影响当前shell会话) shopt -s nullglob arr=( path-to-dir/* ) # 如果你之后不需要这个选项,可以关闭它 shopt -u nullglob - 路径里有特殊字符(比如空格):如果目标目录的路径包含空格或者其他特殊字符,你需要给路径部分单独加引号,把
*留在外面,确保Bash能正确解析路径并扩展通配符:# 比如目录名叫"my docs" arr=( "my docs"/* )
为什么$(ls -1 path-to-dir)不是好选择?
你说得对,用ls来生成文件名列表是脚本里的常见坑,主要问题有:
- 文件名里的特殊字符会拆分数组元素:如果文件名包含空格、制表符甚至换行符,命令替换
$()会把这些当成元素分隔符,导致数组被错误拆分。比如一个叫hello world.txt的文件,用这个方法会被拆成hello和world.txt两个完全错误的元素。 ls的输出是给人看的,不是给脚本解析的:某些系统下ls会输出颜色控制字符、长文件名自动换行,这些都会导致脚本解析出错,稳定性极差。
正确用法的几个示例
- 基本用法(相对/绝对路径都可)
# 相对路径(比如当前目录下的docs文件夹) arr=( ./docs/* ) # 绝对路径 arr=( /home/user/my-files/* )
- 只匹配特定类型的文件
# 只找path-to-dir下的所有.txt文件 arr=( path-to-dir/*.txt )
- 包含隐藏文件(默认
*不匹配.开头的文件)
shopt -s dotglob arr=( path-to-dir/* ) shopt -u dotglob
总结一下:直接用arr=( path-to-dir/* )配合必要的shell选项(比如nullglob)就是最安全、最高效的方法,完全没必要用ls来绕弯路~
内容的提问来源于stack exchange,提问作者camwrangles
相关产品推荐
相关产品推荐

