【发布时间】:2017-02-04 22:30:44
【问题描述】:
试图弄清楚如何包含所有.txt 文件,但名为manifest.txt 的文件除外。
FILES=(path/to/*.txt)
【问题讨论】:
试图弄清楚如何包含所有.txt 文件,但名为manifest.txt 的文件除外。
FILES=(path/to/*.txt)
【问题讨论】:
您可以为此使用extended glob patterns:
shopt -s extglob
files=(path/to/!(manifest).txt)
!(<em>pattern-list</em>) 模式匹配“除给定模式之一之外的任何内容”。
请注意,这完全不包括manifest.txt,仅此而已;例如,mmanifest.txt 仍然会进入数组。
附带说明:一个完全不匹配的 glob 会扩展为自身(参见 the manual 和 this question)。可以使用nullglob(扩展为空字符串)和failglob(打印错误消息)shell 选项更改此行为。
【讨论】:
!(manifest).txt 的数组我认为除了extglob 之外,您还需要nullglob
extglob?请注意,它可以在交互式 shell 中打开,但在非交互式 shell 中关闭,以防您在脚本中尝试此操作。 nullglob 不需要,我会说。
nullglob(没有其他任何更改),我就可以从预期结果变为我评论中描述的结果。
.txt 文件的情况?只有这样我才能得到你所描述的内容。
.txt 文件;也许这种情况应该明确处理?
你可以一次构建一个数组,避免你不想要的文件:
declare -a files=()
for file in /path/to/files/*
do
! [[ -e "$file" ]] || [[ "$file" = */manifest.txt ]] || files+=("$file")
done
请注意,for 语句中的通配符不会导致文件名中的空格(甚至换行符)出现问题。
编辑
我添加了一个文件存在测试来处理 glob 失败且未设置 nullglob 选项的情况。
【讨论】:
我认为最好使用关联数组来处理,即使只有一个元素。
考虑:
$ 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
这种方法允许从文件列表中排除任意数量的内容。
【讨论】:
FILES=($(ls /path/to/*.txt | grep -wv '^manifest.txt$'))
【讨论】:
touch 'this * is * a * file.txt' manifest.txt,然后使用它,然后查看FILE 数组包含的内容。
touch 命令创建此文件,它也可以工作。请更正您的示例或解释。
touch 命令,然后你的命令(在$PWD/*.txt),然后printf "'%s' " "${FILES[@]}" 给我'/Users/gordon/tmp/manifest.txt' '/Users/gordon/tmp/this' 'manifest.txt' 'this * is * a * file.txt' 'is' 'manifest.txt' 'this * is * a * file.txt' 'a' 'manifest.txt' 'this * is * a * file.txt' 'file.txt' 。
$() 来防止这种情况,但你最终会得到一个只有一个元素的数组。