查找并使用包含方括号的名称列表中的排除

时间:2017-08-05 13:17:29

标签: bash find

我需要删除非空目录,但根据列表排除一些。该列表包含一些特殊字符,尤其是[]。我可以修改列表以根据需要转义字符,但我没有做任何事情使它们匹配。

我的命令仅适用于简单名称:

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

1 个答案:

答案 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不会删除前导或尾随空格。