lines=$(grep '^[^:]\+::' /etc /shadow) 

What does this whole command mean?

What does '^[^:]\+::' mean?

if I put if else statement like:

if [ "$lines" == "" ]; then 

Will it display (which is what I want) users with empty password?

2 Answers 2


grep is the command that implements the g/<RE>/p command in ed/ex (hence its name), that is, it prints the lines that match a given regular expression (regex or regexp for short).

Here, '^[^:]\+::' is the regular expression (quoted so the shell doesn't treat some of those characters specially). More precisely (as there are several implementations of grep and most can handle several variants of regular expressions), it's a GNU Basic regular expression.

Regular expressions are patterns used to match strings. grep compares the content of each line with that pattern and prints those that match.

  • ^ is the basic regular expression operator that matches at the beginning of the string to be matched. We say it anchors the search at the start of the string, otherwise the search would be anywhere within the line.

  • [^:] matches any character but :

  • \+ is a GNU specific non-standard regexp operator (though nowadays we find other implementations supporting it) that means one or more of the preceding atom. It's a short hand for the standard \{1,\} basic regex operator.

  • : is not special and matches itself.

So here the regexp matches lines that start with a sequence of one or more characters other than : followed by two : characters.

In the context of /etc/shadow, that means it matches on entries that have at least 3 fields and where the username field is not empty but the password field is empty (which usually means users that can login without a password). It will match on root::, x::whatever, but not on root:x: or ::whatever or root:.

grep also reports whether it has matched any line through its exit status:

  • successful if there has been at least one match
  • fail otherwise or if an error occurred.

The exit status of a shell assignment is the exit status of the last command run in a command substitution.

For instance, the exit status of

var=$(exit 2)$(exit 4)

will be 4.

So here, you can do:

if lines=$(grep '^[^:]\+::' /etc/shadow); then
  printf 'There are users with an empty password:\n%s\n' "$lines"
  printf 'OK, no user with empty passwords'

grep '^[^:]\+::' /etc/shadow will not show anything because the Regex pattern is not right.

I am guessing you were to find the users having no password associated i.e. system accounts. In that case do:

grep '^[^:]\+:.:' /etc/shadow

Let's break it down:

  • ^[^:]\+ will find the portion from the start of the line till next : i.e. the username

  • The username will be followed by a :, any single character indicated by Regex token . (possibly ! or *) and then a :.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .