Reading User Input in Linux
I have written a script for listing files based on the month which is read by the user as below:-
echo "Enter Month"
read month
ls -al | awk '$6 == "$month" {print}'
And i am giving the user input as Aug, i am not getting any result. But when i am writing
ls -al | awk '$6 == "Aug" {print}'
I am getting the exact result. Am i doing something wrong? Please help
Solution 1:
The main thing is: variable names are not expanded inside single quotes. This is a "better" (i.e. a little less wrong) line:
ls -al | awk '$6 == "'"$month"'" {print}'
# this is in single quotes ^^^^^^^ ^^^^^^^^^
But:
- Still this may fail in some locales. Set
LC_ALL=C
beforehand or so maybe. - With
$month
you can inject (almost?) anything intoawk
. There are better ways to use variables withinawk
;-v
option should be a lot safer (thank you user000001 for pointing this out). -
You shouldn't parse the output of
ls
in the first place.
The right solution might use find
and stat
. The following code may not be the fastest solution but it's more robust due to:
- discarding
$month
values that don't match predefined ones, - using
find
instead of parsingls
.
The code:
#!/bin/sh
echo "Enter Month"
read month
case "$month" in
1|01|Jan|jan|January|january) monthN=01;;
2|02|Feb|feb|February|february) monthN=02;;
# ...
10|Oct|oct|October|october) monthN=10;;
# ...
*) echo Error! >&2; exit 1;;
esac
find ./ -maxdepth 1 -exec sh -c '[ `stat -c %y "$1" | cut -c 6-7` = "$2" ]' sh {} "$monthN" \; -ls
I tested this on Debian; it may not be super-portable. It shows the general approach though.
The last line invokes a separate shell for every object in the current directory (including ./
itself). This shell uses stat
to get mtime information, then cut
extracts two-digit month number from it. [ ... ]
compares the result to the chosen month number. If this test succeeds then find
performs its own ls
on the object (you may use -print
or -print0
instead).
Note this never returns ../
. On the other hand find
allows you to use additional tests (like -type f
), so this approach is very flexible.