7

I'm currently working through some exercises to try and improve my shell scripting. The requirements of the script are as follows:

  1. It must get the user's name using the whoami command and store it in a variable called username.
  2. It must take a single parameter which is the name of the file to be searched.
  3. It must grep to search the specified file for occurrences of the user's name and print them.

This part is relatively simple, and I've used the following to get it working:

username=$(whoami)
echo 'Enter the name of the file you would like to search: '
read fileName
cat "fileName" | grep "$username"

However there is a catch, the exercise states the following:

Note: for this task there's no need to worry about missing parameters of error checking. The script, apart from shebang and any comments you choose to add, should consist of two lines.

How can I reduce this to only two lines?

Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255

2 Answers2

10

The pathname of the file is given as a parameter. This means that it's given on the command line of the script. This means that you shouldn't interactively ask the user for it.

#!/bin/sh
grep -wF -e "$LOGNAME" "$1"

Alternatively, if you really want to use whoami:

#!/bin/sh
grep -wF -e "$(whoami)" "$1"

Or, for the "two lines" requirement:

#!/bin/sh
name=$(whoami)  # or:  name=$LOGNAME
grep -wF -e "$name" "$1"

Or, if we'd like to do something useful on that first line:

#!/bin/sh
[ ! -f "$1" ] && { printf 'No such file: %s\n' "$1" >&2; exit 1; }
grep -wF -e "$(whoami)" "$1"

The -w option to grep make it match complete words only. grep -w 'AA' would match AA but not AAA.

The -F option to grep makes the utility take the given expression as a fixed string and not as a regular expression.

The -e option signifies that the next string on the command line is the pattern. Without it, a pattern starting with a dash may be mistakenly interpreted as a set of command line options.

The $LOGNAME (or $USER on many systems) variable holds the username of the current user.

The value of $1 is the first command line argument given to the script on the command line.

Also note that we may execute this with /bin/sh rather than with bash as this script uses no special bash-specific shell extensions. It would obviously run just as well under bash...


Note that the above does not search for files mentioning a particular user (as in the title of the question), but rather searches for lines in a file that mentions this user.

To search for files mentioning the current user in a directory given on the command line:

#!/bin/sh
find "$1" -type f -exec grep -q -wF -e "$LOGNAME" {} ';' -print

Related to this last part:

Kusalananda
  • 333,661
1

The simplest solution:

#!/bin/bash
username=$(whoami)
grep $username $1

You can provide grep with a filename as a optional parameter (see man grep). The variable $1 refers to the firs positional parameter of a script.

You call it as follows:

name-finder.sh filename

You can make it even an one-liner:

username=$(whoami); grep $username $1

Or

grep $(whoami) $1
  • 4
    Since you haven quoted any of the expansions, this would fail on filenames containing spaces or possibly filename globbing chraracters. It would also fail if the username contained spaces (although this would admittedly be unlikely). – Kusalananda Oct 08 '18 at 11:13
  • 1
    Thet's true, devil is in the details. Option -wF might be also important, as You have suggested. – Piotr Sawicki Oct 08 '18 at 12:02