Иногда на старых системах Linux я сталкиваюсь с тем, что find
не поддерживаются -writable
тесты -readable
, которые проверяют, доступен ли файл или каталог для записи/чтения для текущего пользователя.
Допустим, я хочу выразить -writable
; тогда -perm -0002
это не будет эквивалентно, так как не проверяется, есть ли у пользователя права на запись с помощью владельца/группы.
Как я могу выразить find
тест -writable
с помощью find
других тестов (например -perm
, )?
решение1
Нет удобного способа. Вот почему GNU find добавил -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
(которые используют эффективные uid и gid процесса Perl — используйте -R
/ -W
/ -X
для проверки с реальным uid/gid, как и access(2)
, и используйтеfiletest 'access'
прагмаесли ваш Perl не слишком древний, чтобы поддерживать такие вещи, как ACL):
use File::Find;
use filetest 'access';
find(sub { if (-r $_) { print "$_ is readable\n"; } }, '.');
В Python, сos.walk
иos.access
(который использует реальные uid и gid процесса Python, например 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"
. Пассивного теста на возможность исполнения обычного файла, на возможность записи каталога или на доступ к большинству нестандартных файлов не существует.