I am asking for the user to input a title, but I want to compare the "input" with my text file - bash

#!/bin/bash
library=mylibrary
tmp=mylibrary.tmp
function add_book {
echo Please enter the book title:
read title
existed=`awk -F '$1 == $title' $library | wc -l`
echo $existed
if (( $existed == 0 ))
then
echo Please enter the author:
read author
location=library
updated=$title,$author,$location,`date +%F`
echo $updated >> $library
echo $updated return successfully!
else
echo "Book Exist!"
fi
((WHAT I WANT TO DO IS COMPARE THE TITLES AND IF THE TITLE EXIST THEN ECHO "BOOK EXIST"
I WANT IT TO COMPARE THE INPUT WITH THE TEXT FILE))
HERE IS A SAMPLE TEXT FILE:
Title,Author,Location,Date Added
jj,jj,library,2013-11-14
hjj,hj,library,2013-11-14
jhj,hjh,library,2013-11-14

Your script has quite a few issues but this seems to be a blocker issue:
existed=`awk -F '$1 == $title' $library | wc -l`
Change that to:
existed=$(awk -v title="$title" -F '$1 == title{i++} End{print i}' "$library")
SHELL doesn't expand varialle inside single quotes
To pass a shell variable to awk use -v name="$value" syntax

Related

finding the string within folder using shell command

How to find all files within folder containing specific text (string) if text found return 1 if not return 0 in linux?
grep -r "34161FA8203289722240CD40" /usr/lib/cgi-bin/ParkingSoft/api/v3/LaneApi/ETC/MywebSocket /*.txt
Try This:
grep -rwl 'PATH/targetFolder/' -e 'target_string' | awk -F "/" '{print $NF}'
The above command returns the name of all files that contains the target_string.
To know about -rwl check this answer, However awk -F "/" '{print $NF}' just split the grep output and return the last part. (file name in your case)
The -q option returns (exit code) 1 when no match is found. Try:
echo "string" | grep -q in && echo yes
echo "string" | grep -q out && echo yes
In your case:
searchdir="/usr/lib/cgi-bin/ParkingSoft/api/v3/LaneApi/ETC/MywebSocket "
if [ ! -d "$searchdir" ]; then
echo "Check searchdir. Is 'ETC' really in uppercase and is `Mywebsocket ` including a space?"
else
if grep -rwq '34161FA8203289722240CD40' "${searchdir}/*.txt; then
echo "String found in one of the files."
fi
fi

How to test if an attribute exists in a file with Bash?

I'm trying to get this tested, but I'm not sure if the if is right
if [ $(lsattr /mnt/backup/*.* | grep i) ] ;
then
echo "file $_ has i attribute";
else
echo "file $_ does not have i attribute"
fi
This is the lsattr on that directory:
----i----------------- /mnt/backup/Backup-Full_02-04-2022.7z
---------------------- /mnt/backup/test.7z
Thank you
With grep i you will also match file names containing i. Moreover, $_ is not set so its value is probably just the empty string. If you really want to use an if statement you also need a loop. And grep is not needed any more if you use the bash conditional expressions:
$ lsattr /mnt/backup/*.* | while read -r attr name; do
if [[ "$attr" == "*i*" ]]; then
echo "file $name has i attribute"
else
echo "file $name does not have i attribute"
fi
done
file /mnt/backup/Backup-Full_02-04-2022.7z has i attribute
file /mnt/backup/test.7z does not have i attribute
If you can use awk instead of grep you can easily limit the search to the first word:
awk '$1 ~ "i"'
And you don't need any bash if or while loop any more, all this can be embedded in the awk script:
$ lsattr /mnt/backup/*.* | awk -vs1=" has " -vs2=" does not have " \
'{print $2 ($1 ~ "i" ? s1 : s2) "i attribute"}'
file /mnt/backup/Backup-Full_02-04-2022.7z has i attribute
file /mnt/backup/test.7z does not have i attribute

Output not displaying after echo

I'm trying to format my output based on the result of a certain command. However, it's not printing out. Can you guys let me know what I am missing out.
VID=$(grep -iE $vvwwn ${TPAR_TEMP}/vvid_${TPAR_NAME} > ${TPAR_TEMP}/tvvid 2> /dev/null)
TVVID=$(cat ${TPAR_TEMP}/tvvid |awk '{print$3}' 2> /dev/null)
if [ "${TVVID}" = "32" ]; then
sh templ1
echo "$VID"
else
sh templ2
echo "$VID"
fi
templ1 is
#!/bin/bash
echo "========================================================================================================"
awk '
BEGIN {printf "%-27s %-6s %-32s %-8s %-8s %-9s %-4s\n" , "Name", "State", "VV_WWN", "VSize_MB", "Usr_Used_MB", "UsrCPG", "Prov"}'
echo "========================================================================================================"
The problem is with $VID been empty due to the redirect in the command grep -iE $vvwwn ${TPAR_TEMP}/vvid_${TPAR_NAME} > ${TPAR_TEMP}/tvvid, To make the problem easier fill in the variables and run the command in your terminal.

bash script grep the etc file for user information

I am trying to write a script in bash to read in arguments (usernames) and then return information about that username by searching the /etc/passwd file. I am not the root on the server that I am scripting this on, but I don't need to be. Here is the code that I have so far, but I dont think I am using the grep command right.
#!/bin/bash
if [ $# -eq 1 ]; then #if num of args =1; then continue on
UNAME=$1 #set arg to var UNAME
grep UNAME=$(grep $/etc/passwd)
if [ $UNAME == /etc/passwd ]; then #if UNAME exists then display info below
echo "-------------------------------------------"
echo "Username: $(grep UNAME/etc/passwd/ $f1) "
echo "User ID (UID): $(grep UNAME/etc/passwd/) "
echo "Group ID (GID): $(grep UNAME/etc/passwd/) "
echo "User info: $(grep UNAME/etc/passwd/) "
echo "Home directory: $(grep UNAME/etc/passwd/) "
echo "Command shell: $(grep UNAME/etc/passwd/) "
echo "-------------------------------------------"
else #if UNAME is nonexistant then display this error message
echo "-------------------------------------------"
echo ""$UNAME" does not exist."
echo "-------------------------------------------"
fi
fi
if [ $# -eq 0 ]; then #if num of args =0; then display this
echo "Not enough arguments provided."
echo "USAGE: $0 <user_name> [user_name] ..."
exit 1
fi
You're doing too much. grep is the wrong tool for the type of parsing you are trying to do. The solution given here is pretty sloppy since it reads the passwd file once for each user you are querying instead of reporting everything in one pass, but it's not unreasonable:
#!/bin/sh
for UNAME; do
while IFS=: read login passwd uid gid name home shell; do
if test "$login" = "$UNAME"; then
echo "-------------------------------------------"
echo "Username: $login"
echo "User ID (UID): $uid"
echo "Group ID (GID): $gid"
echo "User info: $name"
echo "Home directory: $home"
echo "Command shell: $shell"
echo "-------------------------------------------"
continue 2
fi
done < /etc/passwd
echo "No entry for user $UNAME" >&2
done
Before I get to the explanation, here is how I would have written your script:
cat ./test.sh
#!/bin/bash
UNAME=${1} #set arg to var UNAME
if [ -z ${UNAME} ]; then #if no argument is provided; then display this
echo "Not enough arguments provided."
echo "USAGE: $0 <user_name>"
exit 1
fi
if grep ${UNAME} /etc/passwd >/dev/null; then #if UNAME exists then display info below
echo "-------------------------------------------"
echo "Username: $(awk -F ':' -v uname=${UNAME} '$0 ~ uname {print $1}' /etc/passwd)"
echo "User ID (UID): $(awk -F ':' -v uname=${UNAME} '$0 ~ uname {print $3}' /etc/passwd)"
echo "Group ID (GID): $(awk -F ':' -v uname=${UNAME} '$0 ~ uname {print $4}' /etc/passwd)"
echo "User info: $(awk -F ':' -v uname=${UNAME} '$0 ~ uname {print $5}' /etc/passwd)"
echo "Home directory: $(awk -F ':' -v uname=${UNAME} '$0 ~ uname {print $6}' /etc/passwd)"
echo "Command shell: $(awk -F ':' -v uname=${UNAME} '$0 ~ uname {print $7}' /etc/passwd)"
echo "-------------------------------------------"
else #if UNAME is nonexistant then display this error message
echo "-------------------------------------------"
echo "\"${UNAME}\" does not exist."
echo "-------------------------------------------"
fi
Explanation:
if can use grep directly to check for the existence of
your argument in passwd
UNAME= is how arguments are assigned, not
called - they are called with the $ - for example $UNAME
/etc/passwd is an absolute file name and not an argument, thus
$/etc/passwd doesn't mean anything to bash
argument=$(any old bash command) is telling bash that you want to
assign the output of "any old bash command" to "argument", so $()
has to contain a command with output for "argument" to be assigned
anything.
the >/dev/null sends the output of grep to the waste basket because we only care at this point whether or not it's successful so that if knows what to do
grep works like this: grep <the thing you want to find> <file> (note that spaces matter and to use "" if you want to include spaces in your search)
to get specific fields, awk is more useful. awk -F':' tells awk that I want : to define my field separators; -v uname=${UNAME} passes my argument to awk; within awk, $0 ~ uname checks the line for my argument (like grep); and {print $1} prints the first field, and so on
Also consider the limitation of partial matches. If, for example, I have a user JSmith and Smith, searching Smith will return both. This can be addressed with regex but will add a great deal of complexity to the script.
Here is a version with lighter awk usage which works with multiple arguments:
#!/bin/bash
for username; do
if grep ${username} /etc/passwd >/dev/null; then #if username exists then display info below
echo "---------------------------------------"
awk -F':' -v uname="${username}" '\
$0 ~ uname \
{print " Username: "$1\
"\n User ID (UID): "$3\
"\n Group ID (GID): "$4\
"\n User info: "$5\
"\n Home directory: "$6\
"\n Command shell: "$7}' /etc/passwd
echo "---------------------------------------"
else #if username is nonexistant then display this error message
echo "---------------------------------------"
echo "\"${username}\" does not exist."
echo "---------------------------------------"
fi
done
if [ -z ${1} ]; then #if no argument is provided; then display this
echo " Not enough arguments provided."
echo " USAGE: $0 <user name>"
exit 1
fi
*Credit to William Pursell for explaining the for loop
The best tool to read databases such as passwd is getent. This will fetch entries from a database supported by Name Service Switch Libraries. If you really need to limit reading the files databases, you can tell getent to use files database with -s files.
Your code is unnecessarily long. Fetching a record and parsing them into multiple variables should be enough.
#!/bin/bash
if [ $# -eq 1 ]; then #if num of args =1; then continue on
if IFS=: read username ignore uid gid gecos home shell < <(getent -s files passwd $1); then
echo "-------------------------------------------"
echo "Username: $username"
echo "User ID (UID): $uid"
echo "Group ID (GID): $gid"
echo "User info: $gecos"
echo "Home directory: $home"
echo "Command shell: $shell"
echo "-------------------------------------------"
else #if $1 is nonexistant then display this error message
echo "-------------------------------------------"
echo "'$1' does not exist."
echo "-------------------------------------------"
fi
fi
if [ $# -eq 0 ]; then #if num of args =0; then display this
echo "Not enough arguments provided."
echo "USAGE: $0 <user_name> [user_name] ..."
exit 1
fi

linux script to update price

i would like to do a code that prompts user to input the title and author of a book and i want to use grep to get the data based on just the title and author and echo it back for the user to see and edit the price without having the user to enter the old price
I need help in trying to get the $price Variable just by entering the title and author
function update_cost
{
echo "Title: "
read title
echo "Author: "
read author
grep -iqs "$title:$author:$price:" BookDB.txt && echo "$title:$author:$price:"
echo "New Price: "
read price_r
sed -i "/^$title:$author:/ s/$price/$price_r" BookDB.txt || tee BookDB.txt && echo "Book Price has been updated sucessfully!"
}
In regards to the question above i came up with an answer for that. Hope it Helps
price=$(echo "$result" | cut -f 3 -d ":")
I manage to get the 3rd field of what the user input by matching it with the result line followed by using the sed line i edited the third field.
function update_cost
{
echo "Enter Title: "
read title
echo "Enter Author: "
read author
result=$(grep -ise "$title\:$author" BookDB.txt)
price=$(echo "$result" | cut -f 3 -d ":")
grep -iqs "$title:$author:$price:" BookDB.txt && echo "Book Found!"
echo "New Price: "
read new_price
sed -i "/^$title:$author:$price:/ s/$price/$new_price/" BookDB.txt || tee BookDB.txt && echo "Price has been updated sucessfully!"
}
awk is better suited to extracting a field from the file and assigning it to a variable.
function update_cost
{
echo "Title: "
read title
echo "Author: "
read author
price=$(awk -F: -v title="$title" -v author="$author" '$1 == title && $2 == author { print $3 }' BookDB.txt)
echo "Old price is $price"
echo "New Price: "
read price_r
sed -i "/^$title:$author:/ s/:$price:/:$price_r:/" BookDB.txt || tee BookDB.txt && echo "Book Price has been updated sucessfully!"
}

Resources