Aby poradzić sobie z dowolnymi nazwami plików (w tym zawierającymi znaki nowego wiersza), zwykłą sztuczką jest znajdowanie plików w środku .//.zamiast .. Ponieważ //normalnie nie może się zdarzyć podczas przeglądania drzewa katalogów, masz pewność, że //sygnał wyjściowy find(lub tutaj lsattr -R) sygnalizuje początek nowej nazwy pliku .
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()}'
Zauważ, że wyjście nadal będzie oddzielone znakiem nowej linii. Jeśli musisz go przetworzyć później, musisz go dostosować. Na przykład, możesz dodać a, -v ORS='\0'aby móc karmić go GNU xargs -r0.
Zauważ również, że lsattr -R(przynajmniej 1.42.13) nie może zgłosić flag plików, których ścieżka jest większa niż PATH_MAX (zwykle 4096), więc ktoś może ukryć taki niezmienny plik, przenosząc jego katalog nadrzędny (lub dowolny ze składników ścieżki, które prowadzą do z wyjątkiem siebie, ponieważ jest niezmienny) do bardzo głębokiego katalogu.
Obejściem byłoby użycie findz -execdir:
find . -execdir sh -c '
a=$(lsattr -d "$1") &&
case ${a%% *} in
(*i*) ;;
(*) false
esac' sh {} \; -print0
Teraz, z -print0, to jest przetwarzalne, ale jeśli zamierzasz cokolwiek zrobić z tymi ścieżkami, zwróć uwagę, że każde wywołanie systemowe na ścieżkach plików większych niż PATH_MAX nadal nie powiedzie się, a komponenty katalogu mogą zostać zmienione w przedziale czasowym.
Jeśli mamy uzyskać rzetelny raport o drzewie katalogów, który może zostać zapisany przez innych, istnieje kilka innych problemów związanych z samym lsattrpoleceniem, o których powinniśmy wspomnieć:
- sposób
lsattr -R .przechodzenia przez drzewo katalogów, podlega warunkom wyścigu. Można sprawić, że zejdzie do katalogów spoza drzewa katalogów kierowanych do ., zastępując niektóre katalogi dowiązaniami symbolicznymi w odpowiednim momencie.
lsattr -d filema nawet warunki wyścigowe. Te atrybuty mają zastosowanie tylko do zwykłych plików lub katalogów. Tak lsattrrobi lstat()najpierw sprawdzić, czy plik ma odpowiednich typów i wtedy nie open()następuje ioctl()do pobierania atrybutów. Ale wywołuje open()bez O_NOFOLLOW(ani O_NOCTTY). Ktoś mógłby zastąpić filew jego miejsce linku do /dev/watchdogna przykład pomiędzy lstat()a open()i spowodować, że system restartu. Powinno to open(O_PATH|O_NOFOLLOW)nastąpić fstat(), openat()a ioctl()tutaj, aby uniknąć warunków wyścigu.