Чтобы иметь дело с произвольными именами файлов (включая те, которые содержат символы новой строки), обычная хитрость заключается в том, чтобы искать файлы внутри, .//.
а не .
. Поскольку //
при обходе дерева каталогов обычно это не происходит, вы уверены, что в выходных данных (или здесь ) появляется //
сигнал начала нового имени файла .find
lsattr -R
lsattr -R .//. | awk '
function process() {
i = index(record, " ")
if (i && index(substr(record,1,i), "i"))
print substr(record, i+4)
}
{
if (/\/\//) {
process()
record=$0
} else {
record = record "\n" $0
}
}
END{process()}'
Обратите внимание, что выходные данные по-прежнему будут разделены новой строкой. Если вам нужно постобработать его, вам придется адаптировать его. Например, вы можете добавить a, -v ORS='\0'
чтобы иметь возможность передавать его в GNU xargs -r0
.
Также обратите внимание, что lsattr -R
(по крайней мере, 1.42.13) не может сообщить флаги файлов, путь которых больше, чем PATH_MAX (обычно 4096), поэтому кто-то может скрыть такой неизменный файл, переместив его родительский каталог (или любой из компонентов пути, которые приводят к это, за исключением самого себя, поскольку это является неизменным) в очень глубокий каталог.
Обходной путь будет использовать find
с -execdir
:
find . -execdir sh -c '
a=$(lsattr -d "$1") &&
case ${a%% *} in
(*i*) ;;
(*) false
esac' sh {} \; -print0
Теперь, с -print0
, это пост-процессинг, но если вы собираетесь что-то делать с этими путями, обратите внимание, что любой системный вызов на пути к файлам, превышающим PATH_MAX, все равно будет неудачным, и компоненты каталога могли бы быть переименованы в интервале.
Если мы хотим получить надежный отчет о дереве каталогов, который может быть записан другими, есть еще несколько проблем, присущих самой lsattr
команде, о которых нам нужно упомянуть:
- способ
lsattr -R .
прохождения дерева каталогов, это зависит от условий гонки. Можно сделать так, чтобы он спускался в каталоги за пределами дерева каталогов, на .
которое маршрутизируется , заменяя некоторые каталоги символическими ссылками в нужный момент.
- даже
lsattr -d file
имеет состояние гонки. Эти атрибуты применимы только к обычным файлам или каталогам. Так что lsattr
делает lstat()
первым , чтобы проверить , что файл правых типов , а затем делает open()
затем , ioctl()
чтобы извлечь атрибуты. Но это вызывает open()
без O_NOFOLLOW
(ни O_NOCTTY). Кто-то может заменить file
символическую ссылку, /dev/watchdog
например, между lstat()
и open()
и привести к перезагрузке системы. Он должен делать open(O_PATH|O_NOFOLLOW)
затем fstat()
, openat()
и ioctl()
здесь , чтобы избежать условий гонки.