Ich versuche, eine Liste von Benutzern zu erstellen, für die ein nicht vorhandenes Basisverzeichnis festgelegt ist. Es scheint, ich sollte dies mit awk tun können, aber etwas stimmt nicht mit meiner Syntax.
Es sagt mir immer wieder "Ungültige Syntax" an der]. Was mache ich falsch?
awk -F: '{ if(![ -d "$6"]){ print $1 " " $3 " " $7}}' /etc/passwd
Der letzte Code, den ich wahrscheinlich verwenden werde, ist:
awk -F: '{if(system( "[ -d " $6 " ]") == 1 && $7 != "/sbin/nologin" ) {print "The directory " $6 " does not exist for user " $1 }}' /etc/passwd
Und ich habe hier eine verwandte Frage .
/bin/ls
:echo ';ls;' | awk '{ print system("[ ! -d " $1 " ]") }'
Ich denke nicht, dass
[ -d ]
das eineawk
Sache ist, das ist eine Muschelsache. Ich würde es stattdessen einfach so machen:Natürlich können Sie, wie von @Janis sehr richtig hervorgehoben, das Ganze in der Shell erledigen:
quelle
awk
nicht wirklich benötigt wird; da du sowieso in der shell schleifst, kannst du das auch einfach machenwhile IFS=: read -r name x uid x x x shell rest ; do ... ; done </etc/passwd
.awk -F: '{print $6}' /etc/passwd | while read dir; do [ -d "$dir" ] || echo "no results for $dir"; done
.[ -d "$6"]
ist eigentlich Bash-Syntax, nicht awk. Das[
sieht aus wie normale Syntax, aber (in einer der besseren Verrücktheiten von bash / Linux) ist es tatsächlich ein Synonym für dastest
ausführbare Programm (oder vielleicht eine in bash integrierte Version davon, und um seltsamer zu sein, erfordert bash ein Matching]
, das dies nicht tut Ich tue nichts, was mir bewusst ist, außer dich irrezuführen, um zu glauben, dass das Ganze wirklich Syntax und kein Programm ist. Auf jeden Fall weiß awk nichts darüber. Aus diesem Grund benötigen Sie diesystem()
Funktion, um darauf zugreifen zu können, indem Sie sie im Kontext von Bash referenzieren, wo sie verstanden wirdSie können getline verwenden :
quelle
awk
, funktioniert aber leider nicht für Verzeichnisse.Wenn Sie wirklich verwenden
gawk
(obwohl Sie möglicherweise verwendennawk
odermawk
in diesem Fall nicht zutreffen), können Sie dies nativ mit einer der seit Version 4.0 verfügbaren ladbaren Erweiterungen tun. Ich verwendegawk-4.1.x
(v4.0 hatte eine Variation der Syntax zum Laden von Erweiterungen).Durch das Laden der
filefuncs
Erweiterung wird (unter anderem) einestat()
Funktion hinzugefügt:Weitere
filefuncs(3am)
Informationen zu dieser Erweiterung finden Sie in der Manpage.Laufen Sie mit so etwas wie:
Sie können bestätigen, dass Ihre
gawk
Binärdatei Erweiterungen unterstützt, mit:Nebenbei:
gawk
Kommt auch mit einer kleinen Bibliotheksfunktion zum Lesen derpasswd
Datei, können Sie sie wie folgt aufrufen:Ich bevorzuge die Verwendung
getent
auf Linux / glibc-Systemen, da es nsswitch unterstützt.quelle
gawk
v4 dies anbietet. Vielen Dank!Es ist fast awk ...
quelle
Hier ist eine Lösung, die
gawk
und/bin/sh
Code:
erklärt:
IFS="" read -r dir; [ -d "$dir" ]; echo $?
ist ein Shell-Code, der einen Pfad aus stdin liest und ausgibt,0
wenn es sich um ein Verzeichnis handelt1
print $6 |& cmd
leitet den Dateinamen an den Befehl weiter.|&
ist eine GNU-awk-Erweiterung.cmd |& getline x
liest die Ausgabe des Befehls in GNU-awkclose(cmd)
Beendet den Befehl, damit die nächste Zeile einen erneut ausführen kannif (x)
führt dasprint
nur aus wennx
nicht0
(also existiert das Verzeichnis nicht)Ich empfehle jedoch nicht, dies so zu tun, da es sehr langsam und ungeschickt ist. Aber dieses Rezept ist sicher , so dass unregelmäßige Eingabe nicht schaden kann. (Es ist unwahrscheinlich, dass
/etc/passwd
schädliche Daten enthalten sind, aber vielleicht möchte jemand sie mit Daten aus einer nicht vertrauenswürdigen Quelle verwenden.)Wenn Sie nicht verwenden können
gawk
, ist dies unglücklich. In diesem Fall haben Sie nicht|&
. Normalawk
kann nur eine der folgenden drei Aufgaben ausführen:print "data" | cmd; close(cmd)
: Pipe Daten in einen Befehlgetline data < cmd; close(cmd)
: Daten aus einem Befehl lesenret = system(cmd)
: Holen Sie sich den Rückkehrcode des Befehls"Normal"
awk
kann einfach keine Daten in ein Skript leiten und gleichzeitig wieder etwas daraus herausholen (zumindest habe ich keinen Weg dafür gefunden), daher benötigen Sie eine Zwischendatei (tempfile), die noch ungeschickter ist.Die interessante Beobachtung ist, dass eine so einfache Aufgabe auch nur mit der Schale erledigt werden kann:
Sie brauchen nicht
bash
, jede normale Bourne-Shell kann den obigen Code ausführen.Beachten Sie, dass der obige Shell-Code etwas ausgefeilter ist als wirklich benötigt, aber dies soll ein Hinweis darauf sein, wie man wirklich damit arbeitet (für Leute, die nicht vollständig mit der Funktionsweise von Shell vertraut sind).
quelle