Próbuję wygenerować listę użytkowników, którzy mają zestaw katalogów domowych, który nie istnieje. Wydaje się, że powinienem być w stanie to zrobić za pomocą awk, ale coś jest nie tak z moją składnią.
Ciągle mówi mi „nieprawidłowa składnia” w]. Co ja robię źle?
awk -F: '{ if(![ -d "$6"]){ print $1 " " $3 " " $7}}' /etc/passwd
Ostateczny kod, którego prawdopodobnie skończę, to:
awk -F: '{if(system( "[ -d " $6 " ]") == 1 && $7 != "/sbin/nologin" ) {print "The directory " $6 " does not exist for user " $1 }}' /etc/passwd
Mam tutaj podobne pytanie .
/bin/ls
:echo ';ls;' | awk '{ print system("[ ! -d " $1 " ]") }'
Nie sądzę, że
[ -d ]
to jestawk
coś, to jest sprawa skorupy. Zamiast tego zrobiłbym to w ten sposób:Oczywiście, jak bardzo słusznie zauważył @Janis, możesz zrobić wszystko w powłoce:
źródło
awk
tak naprawdę nie jest potrzebne; skoro i tak zapętlasz powłokę, możesz po prostu to zrobićwhile 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"]
rzeczywistości jest to składnia bash, a nie awk. Że[
wygląda jak normalny składni, ale (w jednym z bash / lepszych weirdnesses Linuksa) to właściwie synonim dlatest
programu wykonywalnego (a może bash wbudowanych w wersji niej, a po prostu być dziwniejsze, bash wymaga dopasowania]
tego nie robi nie rób niczego, o czym jestem świadomy, poza wprowadzaniem cię w błąd, aby myśleć, że całość jest naprawdę składnią, a nie programem). W każdym razie nie jest to coś, o czym wie awk. Właśnie dlatego potrzebujeszsystem()
funkcji, aby uzyskać do niej dostęp, odwołując się do niej w kontekście bash, w którym jest to zrozumiałeMożesz użyć getline :
źródło
awk
, ale niestety nie działa w przypadku katalogów.Jeśli naprawdę używasz
gawk
(chociaż możesznawk
, lubmawk
w takim przypadku nie będzie to miało zastosowania), możesz to zrobić natywnie, korzystając z jednego z ładowalnych rozszerzeń dostępnych od wersji 4.0. Używamgawk-4.1.x
(wersja 4.0 miała zmienną składnię do ładowania rozszerzeń).Ładowanie
filefuncs
rozszerzenia dodaje (między innymi)stat()
funkcję:Zobacz
filefuncs(3am)
stronę podręcznika, aby uzyskać szczegółowe informacje na temat tego rozszerzenia.Uruchom z czymś takim jak:
Możesz potwierdzić, że Twój
gawk
plik binarny obsługuje rozszerzenia za pomocą:Poza tym: posiada
gawk
również małą funkcję biblioteki do odczytupasswd
pliku, możesz go wywołać w następujący sposób:Wolę używać
getent
w systemach Linux / glibc, ponieważ obsługuje nsswitch.źródło
gawk
oferuje to wersja v4. Dzięki!To prawie awk ...
źródło
Oto rozwiązanie, które
gawk
i/bin/sh
Kod:
wyjaśnione:
IFS="" read -r dir; [ -d "$dir" ]; echo $?
to kod powłoki, który odczytuje ścieżkę ze standardowego wejścia i wyświetla,0
jeśli jest to katalog, w przeciwnym razie1
print $6 |& cmd
potokuje nazwę pliku do polecenia.|&
jest rozszerzeniem GNU-awk.cmd |& getline x
wczytuje dane wyjściowe polecenia do GNU-awkclose(cmd)
kończy polecenie, aby następny wiersz mógł wykonać ponownieif (x)
wykonujeprint
tylko jeślix
nie jest0
(więc katalog nie istnieje)Nie polecam jednak robić tego w ten sposób, ponieważ jest on bardzo powolny i niezdarny. Ale ten przepis jest bezpieczny , tak że nieregularny wkład nie może zaszkodzić. (Jest mało prawdopodobne, że
/etc/passwd
zawiera szkodliwe dane, ale być może ktoś chce użyć go z danymi z niezaufanego źródła).Jeśli nie możesz użyć
gawk
, jest to niefortunne. W takim przypadku nie masz|&
. Normalnaawk
tylko można wykonać jedną z następujących trzech kryteriów:print "data" | cmd; close(cmd)
: Potokuj dane do poleceniagetline data < cmd; close(cmd)
: Odczytywanie danych z poleceniaret = system(cmd)
: Uzyskaj kod powrotu polecenia„Normalny”
awk
po prostu nie może potokować danych do skryptu i jednocześnie wyciągnąć z niego coś (przynajmniej nie znalazłem sposobu na to), więc potrzebujesz jakiegoś pliku pośredniego (pliku tymczasowego), który jest jeszcze bardziej niezręczny.Ciekawym spostrzeżeniem jest to, że tak łatwe zadanie można wykonać również przy użyciu samej powłoki:
Nie potrzebujesz
bash
, każda normalna powłoka Bourne'a może wykonać powyższy kod.Zauważ, że powyższy kod powłoki jest nieco bardziej skomplikowany niż naprawdę potrzebny, ale powinien być wskazówką, jak naprawdę z nim pracować (dla osób, które nie mają pełnego doświadczenia w działaniu powłoki).
źródło