This is my first time posting here so any feedback is very welcome should I be doing something wrong! I'm very new to shell scripting and am trying to write a function that checks whether an item is in a list. In this case I'm checking whether a given argument correspond to an existing user on the system. I really want to avoid false positives by making sure the item is surrounded by spaces but that obviously excludes the first and last item in the list. I figured maybe I could add spaces to the start and end of the list but I can't figure out how to do this. Any tips or pointers are very welcome! My code so far comes from this post. It looks like this:

-->This is the list of existing users

users=$(getent passwd {1000..60000} | awk -F ':' '{print $1}')

-->Function to check whether the given command line argument is in existing users

   [[ $1 =~ (^|[[:space:]])"$2"($|[[:space:]]) ]] && return 0 || return 1

Where $1 is the list of users obtained with getent from passwd file (see above) and $2 is the given (command line) argument I'm trying to validate.

Just as information: for testing purposes I've been trying out the contains function with a list (1 2 3 4). It works if I check this against 2 and 3, but not for 1 and 4.

  • To test whether a username is valid on the system, use the return status of getent passwd "$username" >/dev/null instead. Not posting that as an answer, as a proper answer should probably reference the code that you are using. You also seem to be missing ]] before &&, and you should mention what the values $1 and $2 looks like.
    – Kusalananda
    Jun 11 '19 at 21:01
  • Thanks for your reply! I've clarified my question and added some context. Also fixed the brackets I forgot to type. Jun 11 '19 at 21:37
  • To visualize the input, can you post that formatted list or a portion of it, plus an example of the given argument? Give dummy users instead of the real ones if you want.
    – seshoumara
    Jun 12 '19 at 7:30
  • I've added some information, but I can change the formatting of the list so if I can get this to work for the simple test example I've added I'll be helped greatly! Jun 12 '19 at 15:09

Try the custom function below. It accepts a list where each item is on a separate line. See usage.

contains(){ printf "%s\n" "$1"|grep '^'"$2"'$' > /dev/null; }

The return code is that of the grep command:

  • 0 - if the item was found in the list (full line match, case sensitive)
  • 1 - if the item was not found in the list
  • 2 or higher - if an error occurred (the error message will be printed)

Modifications that you might need to do on the above function to make it work as you want:

  • don't print anything, not even a possible error message: &> /dev/null
  • print everything (the item if present in the list, a possible error message): remove > /dev/null
  • print only if the item is present in the list, don't print a possible error message: 2> /dev/null
  • force the function to return only 0 or 1: && return 0 || return 1;


list="$(getent passwd {1000..60000}|cut -f1 -d:)"
list="$(printf "%s\n" {1..4})"
contains "$list" "$item"
#to see the return code
echo $?
  • Thanks, this helped me find a way that works! Much obliged :) Jun 13 '19 at 13:53
  • @BlueUmbrella51 You welcome. Have a look also on Jim L.'s answer, as grep -Fx "$2" is much better than grep '^'"$2"'$'. If you want to be informed of errors, don't use grep -q. All the best.
    – seshoumara
    Jun 13 '19 at 18:59
  • Thanks, I'll check the man! I upvoted both your answers but since I have no reputation it isn't visible. Jun 13 '19 at 19:28
users="$(getent passwd | awk -F: '{print $1}')"

   grep -qFx "$2" <<< "$1"

Test this with something like:

if contains "$users" "jim"; then
  echo jim is a user
  echo jim is not a user
  • Thanks for the help, much appreciated! Jun 13 '19 at 19:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.