Arrays 目录中除一个以外的所有文件的数组
正在尝试找出如何包含所有Arrays 目录中除一个以外的所有文件的数组,arrays,bash,Arrays,Bash,正在尝试找出如何包含所有.txt文件,除了名为manifest.txt的文件 FILES=(path/to/*.txt) 您可以一次生成一个文件,避免生成不需要的文件: declare -a files=() for file in /path/to/files/* do ! [[ -e "$file" ]] || [[ "$file" = */manifest.txt ]] || files+=("$file") done 请注意,for语句中的globbing不会导致文件名中的空白
.txt
文件,除了名为manifest.txt
的文件
FILES=(path/to/*.txt)
您可以一次生成一个文件,避免生成不需要的文件:
declare -a files=()
for file in /path/to/files/*
do
! [[ -e "$file" ]] || [[ "$file" = */manifest.txt ]] || files+=("$file")
done
请注意,for
语句中的globbing不会导致文件名中的空白(甚至换行)问题
编辑
我添加了一个文件存在性测试,以处理glob失败且未设置nullglob
选项的情况。您可以使用以下方法:
shopt -s extglob
files=(path/to/!(manifest).txt)
!(模式列表)
模式匹配“除一个给定模式外的任何其他模式”
请注意,这完全排除了manifest.txt
和其他内容<例如,code>mmanifest.txt仍然会进入数组
作为旁注:完全不匹配的glob会扩展到自身(请参见和)。使用
nullglob
(扩展为空字符串)和failglob
(打印错误消息)shell选项可以更改此行为。我认为最好使用关联数组来处理此问题,即使只有一个元素
考虑:
$ touch f{1..6}.txt manifest.txt
$ ls *.txt
f1.txt f3.txt f5.txt manifest.txt
f2.txt f4.txt f6.txt
可以为要排除的名称创建关联数组:
declare -A exclude
for f in f1.txt f5.txt manifest.txt; do
exclude[$f]=1
done
然后将文件添加到不在关联数组中的数组:
files=()
for fn in *.txt; do
[[ ${exclude[$fn]} ]] && continue
files+=("$fn")
done
$ echo "${files[@]}"
f2.txt f3.txt f4.txt f6.txt
这种方法允许从文件列表中排除任意数量的内容 如果文件名中有空格和/或通配符(这是完全合法的),这仍然不起作用。尝试
touch“this*is*a*file.txt”manifest.txt
,然后使用它,然后查看文件
数组包含的内容。@GordonDavisson,它可以工作,即使我使用touch
命令创建此文件。请更正您的示例或解释。@GrzegorzGórkiewicz在空目录中运行我的touch
命令,然后运行您的命令(在$PWD/*.txt
),然后运行printf“'%s'”${FILES[@]}
为我提供了'/Users/gordon/tmp/manifest.txt'/Users/gordon/tmp/this''manifest.txt''这*是*a*文件.txt''是*manifest.txt''这*是*a*文件.txt''文件.txt'
。这仍然扩展了通配符。您必须引用$()
来防止出现这种情况,但这样一来,您将得到一个只包含一个元素的数组。@GrzegorzGórkiewicz您测试过我的示例吗?最新的更新仍然失败(尽管稍微不那么严重)。另外,请阅读上的BashFAQ项目。在我做的一个小测试中,它对我不起作用。我得到一个包含的数组!(manifest).txt
我想除了extglob
,您还需要nullglob
。@Fred看起来您没有打开extglob
?请注意,它可以在交互式shell中打开,但在非交互式shell中关闭,以防您在脚本中尝试此操作<代码>空glob是不需要的,我想说。@BenjaminW。我可以确认我已经在一个交互式shell中复制了它。只需禁用nullglob
(没有其他更改),我就可以从预期的结果转换到我的评论中描述的结果。@Fred,在您根本没有任何.txt
文件的情况下?“这是我能得到你所描述的东西的唯一途径。”本杰明。是,否.txt
文件;也许这个案子应该明确处理?
files=()
for fn in *.txt; do
[[ ${exclude[$fn]} ]] && continue
files+=("$fn")
done
$ echo "${files[@]}"
f2.txt f3.txt f4.txt f6.txt