J'essaie de générer une liste d'utilisateurs qui ont un ensemble de répertoires personnels qui n'existe pas. Il semble que je devrais être capable de le faire avec awk, mais quelque chose ne va pas avec ma syntaxe.
Il continue de me dire "Syntaxe invalide" sur le]. Qu'est-ce que je fais mal?
awk -F: '{ if(![ -d "$6"]){ print $1 " " $3 " " $7}}' /etc/passwd
Le code final que je vais probablement finir par utiliser est:
awk -F: '{if(system( "[ -d " $6 " ]") == 1 && $7 != "/sbin/nologin" ) {print "The directory " $6 " does not exist for user " $1 }}' /etc/passwd
Et j'ai une question connexe ici .
/bin/ls
:echo ';ls;' | awk '{ print system("[ ! -d " $1 " ]") }'
Je ne pense pas que ce
[ -d ]
soit uneawk
chose, c'est une chose coquille. Je le ferais simplement de cette façon à la place:Bien sûr, comme l'a très bien souligné @Janis, vous pouvez tout faire dans le shell:
la source
awk
n'est pas réellement nécessaire; puisque vous bouclez dans le shell de toute façon, vous pouvez aussi le fairewhile 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"]
c'est en fait la syntaxe bash, pas awk. La[
syntaxe ressemble à la normale, mais (dans l'une des meilleures bizarreries de bash / Linux), c'est en fait un synonyme dutest
programme exécutable (ou peut-être une version intégrée de bash de celui-ci, et, pour être plus étrange, bash nécessite une correspondance]
qui ne fait pas Je ne fais rien d'autre que de vous induire en erreur en vous disant que le tout est vraiment de la syntaxe et non un programme). En tout cas, ce n'est pas quelque chose que awk sait. C'est pourquoi vous avez besoin de lasystem()
fonction pour y accéder en la référençant dans le contexte de bash où elle est compriseVous pouvez utiliser getline :
la source
awk
, mais ne fonctionne malheureusement pas pour les répertoires.Si vous utilisez vraiment
gawk
(bien que vous puissiez utilisernawk
, oumawk
, dans ce cas, cela ne s'applique pas), vous pouvez le faire de manière native en utilisant l'une des extensions chargeables disponibles depuis la v4.0. J'utilisegawk-4.1.x
(v4.0 avait une variation sur la syntaxe de chargement des extensions).Le chargement de l'
filefuncs
extension ajoute (entre autres) unestat()
fonction:Consultez la
filefuncs(3am)
page de manuel pour plus de détails sur cette extension.Courez avec quelque chose comme:
Vous pouvez confirmer que votre
gawk
binaire prend en charge les extensions avec:À part:
gawk
est également livré avec une petite fonction de bibliothèque pour lire lepasswd
fichier, vous pouvez l'invoquer comme:Je préfère utiliser
getent
sur les systèmes Linux / glibc car il prend en charge nsswitch.la source
gawk
v4 qui offre cela. Merci!C'est presque génial ...
la source
Voici une solution qui
gawk
et/bin/sh
Code:
expliqué:
IFS="" read -r dir; [ -d "$dir" ]; echo $?
est un code shell qui lit un chemin depuis stdin et affiche0
s'il s'agit d'un répertoire, sinon1
print $6 |& cmd
redirige le nom de fichier vers la commande.|&
est une extension GNU-awk.cmd |& getline x
lit la sortie de la commande dans GNU-awkclose(cmd)
termine la commande, afin que la ligne suivante puisse en exécuter une à nouveauif (x)
exécute leprint
seul ifx
n'est pas0
(donc le répertoire n'existe pas)Je ne recommande pas de le faire de cette façon, car c'est très lent et maladroit. Mais cette recette est sûre , de sorte qu'une entrée irrégulière ne peut pas nuire. (Il est peu probable qu'il
/etc/passwd
contienne des données nuisibles, mais peut-être que quelqu'un veut l'utiliser avec des données provenant d'une source non fiable).Si vous ne pouvez pas l'utiliser
gawk
, c'est dommage. Dans ce cas, vous n'en avez pas|&
. Normalawk
ne peut effectuer que l'une des trois actions suivantes:print "data" | cmd; close(cmd)
: Canaliser des données dans une commandegetline data < cmd; close(cmd)
: Lire les données d'une commanderet = system(cmd)
: Récupère le code retour de la commande"Normal"
awk
ne peut tout simplement pas canaliser des données dans un script et en extraire quelque chose en même temps (au moins, je n'ai pas trouvé de moyen), vous avez donc besoin d'un fichier intermédiaire (fichier temporaire) qui est encore plus maladroit.L'observation intéressante est qu'une tâche aussi simple peut être effectuée avec le shell seul:
Vous n'avez pas besoin
bash
, chaque Bourne-shell normal peut exécuter le code ci-dessus.Notez que le code shell ci-dessus est un peu plus élaboré que vraiment nécessaire, mais ce sera un pointeur sur la façon de vraiment travailler avec lui (pour les personnes qui ne sont pas pleinement expérimentées dans le fonctionnement du shell).
la source