如果我们假设 .rmignore 中的所有文件的名称中都不包含换行符,则以下内容可能就足够了:
# Gather our exclusions...
mapfile -t excl < .rmignore
# Reverse the array (put data in indexes)
declare -A arr=()
for file in "${excl[@]}"; do arr[$file]=1; done
# Walk through files, deleting anything that's not in the associative array.
shopt -s globstar
for file in **; do
[ -n "${arr[$file]}" ] && continue
echo rm -fv "$file"
done
注意:未经测试。 :-) 此外,Bash 4 引入了关联数组。
另一种方法可能是用整个文件列表填充数组,然后删除排除项。如果您要处理数十万个文件,这可能不切实际。
shopt -s globstar
declare -A filelist=()
# Build a list of all files...
for file in **; do filelist[$file]=1; done
# Remove files to be ignored.
while read -r file; do unset filelist[$file]; done < .rmignore
# Annd .. delete.
echo rm -v "${!filelist[@]}"
也未经测试。
警告:rm 风险自负。可能含有坚果。保留备份。
我注意到这些解决方案都不会处理您的.rmignore 文件中的通配符。为此,您可能需要一些额外的处理...
shopt -s globstar
declare -A filelist=()
# Build a list...
for file in **; do filelist[$file]=1; done
# Remove PATTERNS...
while read -r glob; do
for file in $glob; do
unset filelist[$file]
done
done < .rmignore
# And remove whatever's left.
echo rm -v "${!filelist[@]}"
而且..你猜对了。未经测试。这取决于$f 扩展为一个全局对象。
最后,如果您想要更重的解决方案,您可以使用find 和grep:
find . -type f -not -exec grep -q -f '{}' .rmignore \; -delete
这将为正在考虑的每个文件运行grep。而且它不是一个 bash 解决方案,它只依赖于 find,这是非常普遍的。
请注意,如果您的文件包含换行符,所有这些解决方案都有出错的风险。