Um mit beliebigen Dateinamen (einschließlich solcher mit Zeilenvorschubzeichen) umzugehen, besteht der übliche Trick darin, Dateien darin zu finden, .//.
anstatt .
. Da //
dies normalerweise beim Durchlaufen des Verzeichnisbaums nicht der Fall sein kann, sind Sie sicher, dass a //
den Beginn eines neuen Dateinamens in der find
(oder hier lsattr -R
) Ausgabe signalisiert .
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()}'
Beachten Sie, dass die Ausgabe weiterhin durch Zeilenumbrüche getrennt ist. Wenn Sie es nachbearbeiten müssen, müssen Sie es anpassen. Zum Beispiel könnten Sie ein hinzufügen -v ORS='\0'
, um es GNUs zuzuführen xargs -r0
.
Beachten Sie auch, dass lsattr -R
(mindestens 1.42.13) die Flags von Dateien, deren Pfad größer als PATH_MAX ist (normalerweise 4096), nicht gemeldet werden können. Daher kann jemand eine solche unveränderliche Datei ausblenden, indem er das übergeordnete Verzeichnis (oder eine der Pfadkomponenten, zu denen sie führen) verschiebt es, außer sich selbst als unveränderlich) in ein sehr tiefes Verzeichnis.
Ein Workaround wäre zu verwenden find
mit -execdir
:
find . -execdir sh -c '
a=$(lsattr -d "$1") &&
case ${a%% *} in
(*i*) ;;
(*) false
esac' sh {} \; -print0
Nun, mit -print0
, das ist nachbearbeitbar, aber wenn Sie irgendetwas mit diesen Pfaden machen wollen, beachten Sie, dass jeder Systemaufruf auf Dateipfaden, die größer als PATH_MAX sind , immer noch fehlschlagen würde und Verzeichniskomponenten in dem Intervall umbenannt werden könnten.
Wenn wir einen zuverlässigen Bericht über einen Verzeichnisbaum erhalten möchten, der möglicherweise von anderen beschrieben werden lsattr
kann, müssen wir noch einige weitere Probleme erwähnen, die mit dem Befehl selbst verbunden sind:
- Die Art und Weise, wie
lsattr -R .
der Verzeichnisbaum durchquert wird, unterliegt den Wettkampfbedingungen. Man kann es zu Verzeichnissen außerhalb des Verzeichnisbaums bringen, an den weitergeleitet wird, .
indem man im richtigen Moment einige Verzeichnisse durch Symlinks ersetzt.
- hat sogar
lsattr -d file
eine Rennbedingung. Diese Attribute gelten nur für reguläre Dateien oder Verzeichnisse. So lsattr
funktioniert ein lstat()
erstes zu prüfen, ob die Datei der richtigen Arten ist und dann nicht open()
gefolgt , ioctl()
die Attribute abzurufen. Aber es ruft open()
ohne O_NOFOLLOW
(noch O_NOCTTY) auf. Jemand könnte durch file
einen Symlink zum /dev/watchdog
Beispiel zwischen lstat()
und ersetzen open()
und einen Neustart des Systems veranlassen. Es sollte also open(O_PATH|O_NOFOLLOW)
gefolgt werden fstat()
, openat()
und ioctl()
hier um die Rennbedingungen zu umgehen.