I need to grep for an exact word in password file but I get two responses back - linux

I am using grep to parse the password file.
When I use
grep -w "avahi" /etc/passwd
I get two responses
avahi and avahi-autoipd
I have not found a method to give me the unique response.
This command is part of a bigger script where the name (avahi) is actually a variable.
This does work when the name is rpc and rpcuser. So I am guessing the it has something to do with the dash (-) in the name.
Actual code:
#!/bin/ksh
getent shadow |cut -d: -f1-2|grep ':!!'| cut -d: -f1 > /tmp/pasck
while read line
do
NOLOGIN=`grep -w $line /etc/passwd | cut -d -f7|cut -d/ -f3`
if [[ $NOLOGIN != "nologin: && $NOLOGIN != "false" ]] ; then
echo "$line" "$NOLOGIN" >> /tmp/pasck.list
fi
done <?tmp/pasck
The script is trying to go through the shadow file and look for users with no passwords. Then I compare the results to the passwd file to find which of those accounts are set to /bin/false or /sbin/nologin. The remainder would be actual users with no password set but allowed on the system.

Keeping things simple - you could include colon that comes after the username in your grep statement:
$ grep "^avahi:" /etc/passwd

You can use awk and explicitly test the first colon-separated field:
awk -F: '$1 = "avahi"' /etc/passwd

Related

How to show all users in bash which does not end with "specific character"s

All the users in the system that dosen't have as an ending character on their names a, s, t, r, m, z must be shown in Bash.
The users names can be obtained from the /etc/passwd file, in the first column. But I can not perceive the correct approach to exclude those characters from the search.
Should I use grep? Or just a cut?
Something like
grep -o '^[^:]*[^astrmz:]:' /etc/passwd | tr -d :
or
cut -d: -f1 /etc/passwd | grep '[^astrmz]$'
[^blah] matches any character but the ones listed, the opposite of [blah].
GNU grep using a lookahead:
grep -Po '^[^:]*[^astrmz:](?=:)' /etc/passwd
Or using awk instead:
awk -F: '$1 ~ /[^astrmz]$/ { print $1 }' /etc/passwd
Or in pure bash without external commands:
while IFS=: read -r name rest; do
if [[ $name =~ [^astrmz]$ ]]; then
echo "$name"
fi
done < /etc/passwd
As you can see, there's lots of potential approaches.
Simple one liner when using bash:
compgen -u | grep -v '[astrmz]$'
The compgen -u command will produce a list of users (without all of the extra fields present in /etc/passwd); compgen is a builtin in bash where it's normally used for username completion.
This should do the trick:
cut -d: -f1 /etc/passwd | grep -vE 's$|t$|r$|m$|z$'
The cut command strips out the username from the password file.
Then grep -v (does the UNMATCHING)
grep -E does multiple matching (OR OR OR)
the $ sign indicates the last character to match
For example , on my mac, I get:
_gamecontrollerd
_ondemand
_wwwproxy
_findmydevice
_ctkd
_applepay
_hidd
_analyticsd
_fpsd
_timed
_reportmemoryexception
(You see no names end with those 5 letters).
Good Luck.

How to list all users in an administrative group in linux

i am using "getent passwd | cut -d : -f 1 | xargs groups > users.txt" but this lists all users and the groups they are in. In my case there are thousands of users I only need the list of users part of a specific group.
current output is in pic I don't need the members of linux_users group
Each record in /etc/group ends with a list of users that have that group as their supplementary group ( See http://linux.die.net/man/5/group ).
To get all members of your target group, you need to get those plus all users who have the target group as their primary group (in /etc/passwd, identified by your target group's number mentioned in /etc/group).
This script will get you both (you can call it group_ls or something like that):
#!/bin/sh
num_membs="$( getent group "$1" |cut -d: -f3,4 )"
num="${num_membs%:*}"; membs="${num_membs#*:}"
( IFS=,
printf '%s\n' $membs
awk -v num=$num -F: ' $4 == num { print $1 } ' /etc/passwd
) | sort -u
Alternatively, based on your approach
getent passwd | cut -d : -f 1 | xargs groups |
grep ":.* $1 .*" |cut -d : -f1
should do it too.
You can pipe to grep to narrow down the list that you get. Use some like grep groupname.
Grep: http://www.gnu.org/software/grep/manual/grep.html
Then you can use awk to only get part of a line.
Awk: http://tldp.org/LDP/abs/html/awk.html
So in your case you could do: getent passwd | cut -d : -f 1 | xargs groups | grep linux_admins | awk {'print $1'} > users.txt
You can also read the list of users associated with a group (example: users below) into an array in bash with the following:
IFS=$',\n' read -a names < <(grep '^users:' /etc/group | sed 's/^.*://')
Then you can access each user in a simple loop, e.g.
for i in ${names[#]}; do echo "$i"; done
This will only work for shells that support indexed arrays and process substitution, otherwise the pipe gymnastics are required.

bash: grep in loop does not grep

I have (probably a obvious/stupid) problem:
I want to loop over a list of paths, cut them and use the strings to grep in log files.
While every step works fine on its own and 'processed manually' results in hits - grep does not find anything when in the loop?
for FILE in `awk -F "/" '{print $13}' /tmp/files_not_visible.uniq`; do
echo -e "\n\n$FILE\n";
grep "$FILE" /var/log/PATH/FILENAME-2015.12.*;
done
I also tried to do a while loop as reverse exercise, but fails with the same non-result
while read FILE; do
echo $FILE;
echo $FILE | awk -F "/" '{print $13}' | grep -f - /var/log/PATH/FILENAME-2015.12.* ;
done < /tmp/files_not_visible.uniq/tmp/files_not_visible.uniq
So, I guess there is some systematic issue, how I handle the search string with grep?
Found it: the list of files contained invisible characters as the last character of the line! Probably the user, who send me the list of files, created it on some other OS! And I only copied -of course- the visible characters when testing by hand!
Fixed the loop by cutting the last character of a line with
> sed -e 's/.$//'

I need a grep command that will pull the usernames only from the /etc/passwd file in linux

I need a grep or another like command that will pull the usernames only from the /etc/passwd file in linux. Anything before the colon. I know this is doing with reg ex however I am not nearly experienced enough...
The following command will give all ACTUAL users, I need a way to pipe to grep or another line of code to only display the username portion.
awk -v LIMIT=500 -F: '{print $1}' '($3>=LIMIT) && ($3!=65534)' /etc/passwd
This should do:
awk -F: '$3>=LIMIT && $3!=65534 {print $1}' LIMIT=500 /etc/passwd
To do this in mostly plain bash:
limit=500
nfsnobody_id=65534
cut -d: -f1,3 /etc/passwd | while IFS=: read username uid; do
(( uid >= limit && uid != nfsnobody_id )) && echo $username
done
Get out of the habit of using VARNAMES_IN_CAPS: one day you'll write PATH=$(dirname $FILE) and then wonder why commands can no longer be found.
You simply need to rewrite the filter part of your awk command a bit. For instance, the following should work:
awk -v LIMIT=500 -F: '{if (($3>=LIMIT) && ($3!=65534)) print $1}' /etc/passwd
Otherwise, to answer your question strictly, if you want to use grep, the command would be
... | grep -o "^[^:]*"
but that would not be the way to go.

Grep - returning both the line number and the name of the file

I have a number of log files in a directory. I am trying to write a script to search all the log files for a string and echo the name of the files and the line number that the string is found.
I figure I will probably have to use 2 grep's - piping the output of one into the other since the -l option only returns the name of the file and nothing about the line numbers. Any insight in how I can successfully achieve this would be much appreciated.
Many thanks,
Alex
$ grep -Hn root /etc/passwd
/etc/passwd:1:root:x:0:0:root:/root:/bin/bash
combining -H and -n does what you expect.
If you want to echo the required informations without the string :
$ grep -Hn root /etc/passwd | cut -d: -f1,2
/etc/passwd:1
or with awk :
$ awk -F: '/root/{print "file=" ARGV[1] "\nline=" NR}' /etc/passwd
file=/etc/passwd
line=1
if you want to create shell variables :
$ awk -F: '/root/{print "file=" ARGV[1] "\nline=" NR}' /etc/passwd | bash
$ echo $line
1
$ echo $file
/etc/passwd
Use -H. If you are using a grep that does not have -H, specify two filenames. For example:
grep -n pattern file /dev/null
My version of grep kept returning text from the matching line, which I wasn't sure if you were after... You can also pipe the output to an awk command to have it ONLY print the file name and line number
grep -Hn "text" . | awk -F: '{print $1 ":" $2}'

Resources