我需要删除非空目录,但根据列表排除一些。该列表包含一些特殊字符,尤其是[
和]
。我可以修改列表以根据需要转义字符,但我没有做任何事情使它们匹配。
我的命令仅适用于简单名称:
find /dir $(printf "! -name %s " $(cat skip_files)) -exec rm -rf {} \;
我的skip_files
列表将是:
dir with [ab] in.the.name
dir with [a] in.the.name
slightly complex
simplename
我已尝试\
和\\
但"
即使slightly complex
名称也无效。
如果我在没有列表的情况下测试命令,则可以按预期使用转义[
和]
。
find ./ -mindepth 1 -maxdepth 1 ! -name "dir with \[a\] in.the.name"
我在debian 9上使用bash。
find (GNU findutils) 4.7.0-git
答案 0 :(得分:2)
您可以暂时更改字段拆分器$IFS
,以便一次处理每一行作为整个字段。但是,这并没有解决全局扩展仍然发生的事实,这也会影响[]
括号,而\
也没有帮助。
(
IFS=$'\n'
find /dir -mindepth 1 -maxdepth 1 \
$(printf '!\n-name\n%s\n' $(<skip_files)) -exec rm -rf {} +
)
或者,您可以为每个文件名grep
。这是安全的但速度较慢。
find /dir -mindepth 1 -maxdepth 1 \
-exec /bin/sh -c 'grep -F -x "$(basename "$1")" skip_files' - {} \;
-o -exec rm -rf {} +
-F
表示文件名是固定字符串,而不是正则表达式; -x
表示必须匹配整行。
如果您更改skip_files
的格式以使其包含整个路径(例如/dir/dir with [ab] in.the.name
),则您不需要额外的shell流程。
find /dir -mindepth 1 -maxdepth 1 \
-exec grep -F -x {} skip_files \; -o -exec rm -rf {} +
最后,您可以使用Bash数组更仔细地构造命令行。
tests=()
while IFS= read -r name; do
tests+=('!' -name "${name}")
done <skip_files
find /dir -mindepth 1 -maxdepth -1 "${tests[@]}" -exec rm -rf {} +
此处,$IFS
暂时设置为空,以便read
不会删除前导或尾随空格。