查找:仅删除我们被允许删除的文件

查找:仅删除我们被允许删除的文件

我用来find删除符合某些条件的文件:

find -type f [more criteria] -delete

一般来说,这工作得很好,但我遇到了其他用户创建的子目录的问题:据我所知,是否允许我删除文件取决于我对父目录的权限。因此,对于另一个用户创建的子目录中包含的文件,上面的命令会失败:

fbrucker@host /tmp $ ls -lh
total 4,0K
drwxrwxr-x 2 root root 4,0K Jun 15 11:44 foo/

fbrucker@host /tmp $ ls -lh foo/
total 0
-rw-rw-r-- 1 fbrucker fbrucker 0 Jun 15 11:44 a
-rw-rw-r-- 1 root     root     0 Jun 15 11:44 b

fbrucker@host /tmp $ find -type f -delete
find: cannot delete ‘./foo/b’: Permission denied
find: cannot delete ‘./foo/a’: Permission denied

没关系,我无法删除这些文件,但缺少权限会导致find以非零状态退出。我想避免这种情况。

在尝试删除无法删除的文件之前,如何过滤掉它们?

请注意,只需过滤掉错误消息即可不是对我来说足够了,因为这仍然会给我留下非零退出代码。另外,完全忽略退出代码对我来说不起作用,因为我确实想捕获其他错误(我真正的find命令更复杂,例如find /somedir -type f -delete我想不是/somedir忽略不存在时引发的错误)。

我知道它对find文件的权限进行了测试(例如,,,-perm),但我认为它们不适用于此处。例如,-readable-writable

fbrucker@host /tmp $ find -type f -writable
./foo/a

即使我无法删除,foo/a因为我没有必要的权限foo

我正在寻找类似-deletable测试的东西,但似乎不存在。

答案1

是的,您需要对父目录具有写访问权限,并且如果该目录已设置位t,则必须是该目录或要取消链接的文件的所有者,并且所有这些都假设 ACL 等其他安全控制未到位并且文件所在的 FS 不是只读的,这使得是可删除的检查比较复杂。

for -readable// -writable-executable非标准)find可以只使用相应的access(R_OK/W_OK/X_OK)系统调用,但没有等效的for取消链接一份文件。

使用 GNU find4.9.0 或更高版本,您可以使用以下命令进行近似:

find . -depth -type d -writable '(' -uid "$EUID" -o ! -perm -o=t ')' -print0 |
  find -files0-from - -mindepth 1 -maxdepth 1 -type f -delete

zsh(还假设像或bash这样的shell设置$EUID。如果没有,请使用"$(id -u)")。

这会将您拥有的文件留在t您不拥有的 -bit 目录中,您需要单独处理这些文件:

find . -depth -type d -writable ! -uid "$EUID" -perm -o=t -print0 |
  find -files0-from - -mindepth 1 -maxdepth 1 -type f -uid "$EUID" -delete

您可能还希望设置pipefailshell 选项以便能够通过第一个find.

使用旧版本的 GNU find,您始终可以执行以下操作:

find . -depth -type d -writable '(' -uid "$EUID" -o ! -perm -o=t ')' -exec sh -c '
  exec find "$@" -mindepth 1 -maxdepth 1 -type f -delete
  ' sh {} +

如果重点是忽略由于访问权限而取消链接文件的失败,您可以这样做:

set -o pipefail
find . -depth -type f -print0 |
  perl -l -0ne '
    unless (unlink($_) || $!{EACCES}) {
      warn "$_: $!\n";
      $ret = 1;
    }
    END {exit $ret}'

答案2

一种解决方法是使用-exec rm {} \;代替-delete,因为find会忽略调用的退出代码-exec

相关内容