Doing my first steps in bash scripting. Managed to do 5/7 exercices so far, stuck in the last two and I cant find a way to solve it.
Here’s a better translation of the requested exercice, the same should be solved using simple commands like sed, echo, cat, uniq, tr, grep, wc, etc:
Write the command line which displays the number of users whose default shell is one of the shells available on your machine. When the command is executed, for each of the shells we would have a result of the same form as the following:
- 0 users have for shell / bin / sh
- 11 users have for shell / bin / bash
- 0 users have for shell / usr / bin / sh
- 0 users have for shell / usr / bin / bash
CodePudding user response:
This how I understood your question, One approach using arrays, Associative array included.
#!/usr/bin/env bash
declare -A Shell_and_Users
while IFS=: read -ra lines; do
login_shell="${lines[-1]}"
((Shell_and_Users["$login_shell"] ))
done < /etc/passwd
To check the value of the associative array Shell_and_Users
run:
declare -p Shell_and_Users
Now loop through the associative array to print the desired output.
for i in "${!Shell_and_Users[@]}"; do
printf -- '- %d users have shell %s\n' "${Shell_and_Users[$i]}" "$i"
done
If that is not the case then edit the question and add more details if the file /etc/shells
should be parse/involve, since the solution above will never print 0 users
.
CodePudding user response:
You are on the right track. You could use the following script :
#!/bin/bash
# usual syntax to read a file line by line
# https://linuxhint.com/while_read_line_bash/
while IFS= read -r shell
do
# if our file contains commented lines, we ignore them
[[ "$shell" =~ ^[[:space:]]*# ]] && continue
count=$(grep -c ".*:$shell" /etc/passwd)
echo "- $count users have shell $shell"
done < /etc/shells
Here, /etc/shells
is a file containing all available login shell on your system.
/etc/passwd
is another system file, containing the list of every user on your system, as well as the shell associated with it (format : <username>:XXX:XXX:XXX:XXX:XXX:<shell>
)
We use grep -c ".*:$shell" /etc/passwd
to find the number of lines in /etc/passwd
that end by :<the current shell>
EDIT: if the professor provides you with a list of shell, you can paste them all in a file (i.e., input.txt
) and replace done < /etc/shells
by done < ./input.txt
CodePudding user response:
Assuming awk
can be used, you can try this
$ cat awk.script
#!/usr/bin/env awk -f
BEGIN {
FS=":"
} $NF=="/bin/bash" {
count_bash
bash=$NF
} $NF=="/usr/bin/bash" {
count_bash2
bash2=$NF
} $NF=="/bin/sh" {
count_sh
sh=$NF
} $NF=="/usr/bin/sh" {
count_sh2
sh2=$NF
} END {
print count_bash " users have a shell for "bash "\n" \
count_bash2" users have a shell for "bash2 "\n" \
count_sh " users have a shell for "sh "\n" \
count_sh2" users have a shell for "sh2 "\n" \
}
This will give output similar to your expected output, however, if the shell is not in use, you will get an empty output with no value or path which may not be ideal.
Output
$ awk -f awk.script /etc/passwd
24 users have a shell for /bin/bash
users have a shell for
2 users have a shell for /bin/sh
users have a shell for