Для роботи з довільними іменами файлів (включаючи ті, що містять символи нового рядка), звичайний трюк - знайти файли всередині, .//.
а не .
. Оскільки //
зазвичай не може виникати під час переходу до дерева каталогів, ви впевнені, що //
сигналізує про початок нового імені файлу у 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()
тут , щоб уникнути умов гонки.