当“find”的可写和可读测试不可用时,如何表达它们?

当“find”的可写和可读测试不可用时,如何表达它们?

有时,在旧的 Linux 系统上,我遇到find不支持-writable-readable测试的情况,即测试文件或目录是否可写/可读。对于当前用户。

说,我要表达-writable; then-perm -0002不会是等价的,因为它不会通过所有者/组来测试用户是否具有写入权限。

我如何通过其他测试来表达find的测试(例如)?-writablefind-perm

答案1

没有什么方便的办法。这就是GNU 寻找添加-readable和朋友的原因。

您可以通过枚举用户所在的组来构建一个近似权限测试的表达式。未经测试。

can_access="( -user $(id -u) -perm -0${oct}00 -o ("
for g in $(id -G); do
  can_access="$can_access -group $g -o"
done
can_access="${can_access% -o} ) -perm -00${oct}0 -o -perm -000${oct} )"
find … $can_access -print

在某些情况下,这不会给出正确的结果,例如,如果存在访问控制列表,或者在边缘情况下,例如-rw----r--拒绝对组的访问。您可以使用与上述相同的技术检查边缘情况,但表达式会变得更加复杂。对于访问控制列表,您需要调用支持它们的工具。

Perl 和 Python 等语言可以轻松访问access(2).find在 Perl 中,与File::Find-r//-w-x(使用 Perl 进程的有效 uid 和 gid — 使用//-R来检查真实的 uid/gid ,并使用-W-Xaccess(2)filetest 'access'杂注如果你的 Perl 不是太古老而不能支持 ACL 之类的东西):

use File::Find;
use filetest 'access';
find(sub { if (-r $_) { print "$_ is readable\n"; } }, '.');

在Python中,用os.walkos.access(它使用Python进程的真实uid和gid,例如access(2)):

import os
for dirpath, dirnames, filenames in os.walk('.', ):
    for filename in filenames:
        filename = os.path.join(dirpath, filenames)
        if os.access(filename, os.R_OK):
            print(filename + ' is readable\n')

唯一完全可靠的方法是尝试打开该文件。这需要外部实用程序,因此会比较慢。要测试常规文件的可读性:

find … -exec sh -c 'exec 2>/dev/null; : <"$0"' {} \; …

要测试可写性,请使用: >>"$0"(这会打开文件进行追加,因此如果文件不可写,则会失败,但它实际上不会修改任何内容,特别是不会更新修改时间)。要测试目录的可读性,请使用ls -- "$0" >/dev/null.要测试目录的可执行性,请使用cd -- "$0".对于常规文件的可执行性、目录的可写性或对大多数非常规文件的访问,没有被动测试。

相关内容