Problem with understanding output in bash code - bash

I have following code in bash:
#!/bin/sh
w=`who | grep $1`
if [ -z "$w" ]; then
echo "$1 ... ";
fi
Could you help me to understand the output of this code.
I can see that it will display given parameters from command line ($1, $2...)
But I don't really understand these 2 lines:
w=`who | grep $1`
if [ -z "$w" ]; then
Could you provide me with some help as I cannot really find much information

Looks to me a script to check if the username you pass as parameter to the script is logged on the system.
For example if you call it with ./check.sh nonexistinguser it will print nonexistinguser ....
Explanation:
w=`who | grep $1`
Execute who, which displays who is logged in, then grep the result for whatever parameter you passed to the script ($1), store the result in a variable called w; have a look here for the docs on -z
if [ -z "$w" ]; then
If "$w" has length zero, execute the body of the if.

Related

How can I get the return value and matched line by grep in bash at once?

I am learning bash. I would like to get the return value and matched line by grep at once.
if cat 'file' | grep 'match_word'; then
match_by_grep="$(cat 'file' | grep 'match_word')"
read a b <<< "${match_by_grep}"
fi
In the code above, I used grep twice. I cannot think of how to do it by grep once. I am not sure match_by_grep is always empty even when there is no matched words because cat may output error message.
match_by_grep="$(cat 'file' | grep 'match_word')"
if [[ -n ${match_by_grep} ]]; then
# match_by_grep may be an error message by cat.
# So following a and b may have wrong value.
read a b <<< "${match_by_grep}"
fi
Please tell me how to do it. Thank you very much.
You can avoid the double use of grep by storing the search output in a variable and seeing if it is not empty.
Your version of the script without double grep.
#!/bin/bash
grepOutput="$(grep 'match_word' file)"
if [ ! -z "$grepOutput" ]; then
read a b <<< "${grepOutput}"
fi
An optimization over the above script ( you can remove the temporary variable too)
#!/bin/bash
grepOutput="$(grep 'match_word' file)"
[[ ! -z "$grepOutput" ]] && (read a b <<< "${grepOutput}")
Using double-grep once for checking if-condition and once to parse the search result would be something like:-
#!/bin/bash
if grep -q 'match_word' file; then
grepOutput="$(grep 'match_word' file)"
read a b <<< "${grepOutput}"
fi
When assigning a variable with a string containing a command expansion, the return code is that of the (rightmost) command being expanded.
In other words, you can just use the assignment as the condition:
if grepOutput="$(cat 'file' | grep 'match_word')"
then
echo "There was a match"
read -r a b <<< "${grepOutput}"
(etc)
else
echo "No match"
fi
Is this what you want to achieve?
grep 'match_word' file ; echo $?
$? has a return value of the command run immediately before.
If you would like to keep track of the return value, it will be also useful to have PS1 set up with $?.
Ref: Bash Prompt with Last Exit Code

Bash - not enough arguments

I have never used bash before but I am trying to understand this piece of code. The script is supposed to display all log in names, full names and their user-ids. However, whenever I run I can not get past the first if statement and if I delete the statement, it does not work.
#!/bin/bash
if [ $# -lt 1 ];
then
printf "Not enough arguments - %d\n" $#
exit 0
fi
typeset user=""
typeset name=""
typeset passwdEntry=""
while [ $# -ge 1 ];
do
user=$1
shift
name=""
passwdEntry=`grep -e ^$user /etc/passwd 2>/dev/null`
if [ $? -eq 0 ]; then
name=`echo $passwdEntry|awk -F ':' '{print $5}'`
fi
echo "$user $name"
done
$# means "the number of arguments to the current Bash program", and $1 means "the first argument to the current Bash program".
So your problem is that you're not passing any arguments to the program; for example, instead of something like this:
./foo.sh
you'll need to write something like this:
./foo.sh USERNAME
As you are new to Bash, I highly recommend skimming and bookmarking the Bash Reference Manual, http://www.gnu.org/software/bash/manual/bashref.html. It's all on a single page, so you can use your browser's "find in page" function (typically Ctrl+F) to search for things.

How can I make bash evaluate IF[[ ]] from string?

I am trying to create a "Lambda" style WHERE script.
I want lambdaWHERE to take piped input and pass it through if condition after given as arguments is met. Like xargs I use {} to represent what comes down the pipe.
I call command like:
ls -d EqAAL* | lambdaWHERE.sh -f {}/INFO_ACTIVETICK
I want the folder names passed through if they contain a file called INFO_ACTIVETICK
Here is the script:
#!/bin/sh
#set -x
ARGS=$*
while read i
do
CMD=`echo $ARGS | sed 's/{}/'$i'/g'`
if [[ $CMD ]]
then
echo $i
fi
done
But when I run it a mysterious "-n" appears...
$ ls -d EqAAL* | /q/lambdaWHERE.sh -f {}/INFO_ACTIVETICK
+ ARGS='-f {}/INFO_ACTIVETICK'
+ read i
++ echo -f '{}/INFO_ACTIVETICK'
++ sed 's/{}/EqAAL-1m/g'
+ CMD='-f EqAAL-1m/INFO_ACTIVETICK'
+ [[ -n -f EqAAL-1m/INFO_ACTIVETICK ]]
+ echo EqAAL-1m
EqAAL-1m
+ read i
How can I get the bit in the [[ ]] correct?
You were quite close. you only need to switch to the standard POSIX [ $CMD ] and it will work.
The main difference between using [[ $CMD ]] and [ $CMD ] is that the first has fewer surprises and you need not quote variables. That also means that a variable is though of as one token and cannot have a whole expression in it like you are trying. [ $CMD ] however works the same way as the original shell where [ was just a command an thus need explicit quotations in order to interpret something with spaces as one argument.
There is a relevant question about the differences between [[ ...]] and [ ..]

Check number of lines returned by bash command

I have a command similar to this:
LIST=$(git log $LAST_REVISION..$HEAD --format="%s" | egrep -o "[A-Z]-[0-9]{1,4}" | sort -u)
Now, I need to do something if $LIST returned zero or more lines. Here's what I've tried:
if [ ! $($LIST | wc -l) -eq 0 ]; then
echo ">0 lines returned"
else
echo "0 lines returned"
fi
But it throws me an error. What's the correct syntax of doing this (with some details on the syntax used, if possible)?
To check whether a variable is empty, use test -z, which can be written several ways:
test -z "$LIST"
[ -z "$LIST" ]
with bash (or many other "modern" shells):
[[ -z $LIST ]]
I prefer the last one, as long as you're using bash.
Note that what you are doing: $($LIST | ...) is to execute $LIST as a command. That is almost certain to create an error, and guaranteed to do so if $LIST is empty.

BASH script accepting parameters

I have to write a script that accepts 1+ source files and destination directory as arguments. I've attempted to write an error message for filenames that contain spaces, but its getting an error when I enter more than 1 argument with a space in between as well. Any help would be appreciated.. This is what I wrote so far:
if [ "$#" -eq "$(echo "$#" | wc -w)" ]
then
echo "Invalid arguments. Filenames may not contain spaces."
echo "usage: bkup file1 [file2...] bkup_directory"
exit 13
fi
You MAY want to try:
if [ $filename == "*" "*" ]; then
echo your error message here
fi
for the testing of spaces in filenames.
As for actually getting the args
$1 is the variable for the first arg and $2 for the second and so on so something like this might work:
if [ $2 == "*" ]; then
echo NO NO NO NOT TODAY!!!
fi
this would check to see if the second argument says anything at all and so if it did we can assume that it is part of the file name (THIS WOULD ONLY WORK IF THE FILENAME IS THE LAST ARGUMENT) OR:
if [ $2 == "*" ]; then
fil=$1 + \
filename=&fil + $2
fi
this would automatically change their filename into an acceptable format for the system an you would not need an error message.
but i am also new to bash so this could not be what you are looking for or I could have the right idea and all this could be complete whooey..... But if I helped then I'm glad I could.

Resources