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 find
z -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 lsattr
poleceniem, 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 file
ma nawet warunki wyścigowe. Te atrybuty mają zastosowanie tylko do zwykłych plików lub katalogów. Tak lsattr
robi 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ć file
w jego miejsce linku do /dev/watchdog
na 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.