Чтобы иметь дело с произвольными именами файлов (включая те, которые содержат символы новой строки), обычная хитрость заключается в том, чтобы искать файлы внутри, .//.а не .. Поскольку //при обходе дерева каталогов обычно это не происходит, вы уверены, что в выходных данных (или здесь ) появляется //сигнал начала нового имени файла .findlsattr -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()здесь , чтобы избежать условий гонки.