当我使用find
这些参数运行时,它会返回数千个文件:
steven@nook:/mnt/station/media $ sudo find . -not -user steven -or -not -group users | wc
3508 17479 245851
steven@nook:/mnt/station/media $
当我添加一个-exec
参数时,它的行为就像find
没有返回结果并且返回代码表示成功:
steven@nook:/mnt/station/media $ sudo find . -not -user steven -or -not -group users -exec echo {} \;
steven@nook:/mnt/station/media $ echo $?
0
steven@nook:/mnt/station/media $
(我的目标是使用-exec chown -v steven:users {} \;
结果(因此sudo
),但我使用-exec echo {} \;
上面来更清楚地说明问题并排除chown
作为一个促成因素。)
我在 Ubuntu Xenial 上的 stock bash 下使用 gnu find:
steven@nook:/mnt/station/media $ find --version
find (GNU findutils) 4.7.0-git
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Written by Eric B. Decker, James Youngman, and Kevin Dalley.
Features enabled: D_TYPE O_NOFOLLOW(enabled) LEAF_OPTIMISATION FTS(FTS_CWDFD) CBO(level=2)
steven@nook:/mnt/station/media $ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=16.04
DISTRIB_CODENAME=xenial
DISTRIB_DESCRIPTION="Ubuntu 16.04.2 LTS"
steven@nook:/mnt/station/media $ echo $SHELL
/bin/bash
steven@nook:/mnt/station/media $
答案1
这是因为相邻操作的隐含绑定-and
比显式绑定更紧密-or
,并且因为从find(1)
手册页来看,“如果表达式不包含除 -prune 之外的其他操作,则对表达式为真的所有文件执行 -print。”
这意味着,find
看看你第一个例子中的表达式,就会发现
(-not -user steven) -or (-not -group users)
并-print
按照您预期的那样执行结果。
Find
然而,你的第二个例子
(-not -user steven) -or ((-not -group users) -and -exec echo {})
这应该会回显属于用户 steven 但不属于组 users 的所有文件。
解决方案是在:之前在表达式周围添加转义括号-exec
:
sudo find . \( -not -user steven -or -not -group users \) -exec echo {} \;
答案2
您需要对命令行做两处修正。
首先,exec 命令的括号需要转义或加引号,以防止它们被 shell 扩展。这在寻找手册页。
手册页中还有一个示例来阐明此要求。
find . -type f -exec file '{}' \;
Runs `file' on every file in or below the current directory. Notice
that the braces are enclosed in single quote marks to protect them from
interpretation as shell script punctuation. The semicolon is similarly
protected by the use of a backslash, though single quotes could have
been used in that case also.
-or
其次,需要用括号(也必须转义)明确表达式的范围和优先级。
经过修正后,以下内容应该可以正常工作:
sudo find . \( -not -user steven -or -not -group users \) -exec echo '{}' \;
无论如何,我更喜欢通过管道传输 find 命令的输出,并使用 xargs 而不是处理 的语法-exec
。
find . -not -user steven -or -not -group users | xargs sudo echo