I'm new to bash scripting & more familiar with python, but lets say I have this script for example.
Problem:
Entire script terminates if null value is inputed, such as accidental pressing enter twice or not putting "n" or "y" when prompted.
Solution Goal:
Instead of terminating, I would like to add exception/error message & perform prompt the user again every time there's a null value or a not an y/n.
read -r -p "Check the test results below.. do they look good enough to continue? [y/N]" response
if pp $response =~ ^([yY[eE][sS]|[yY])$
then
echo "Continuing"
elif [[ $response =~ ^([nN][oO]|[nN])$ ]]
exit
else
# want to use read -r -p prompt again. Perform recursion if possible
exit
fi
I am trying to perform recursion with this builtin type read. I am wondering if there's a simple solution to achieve my goal.
Enclose it inside a while loop
#!/usr/bin/env bash
while read -r -p "Check the test results below.. do they look good enough to continue? [y/N] " response; do
if [[ $response =~ ^([yY[eE][sS]|[yY])$ ]]; then
echo "Continuing"
elif [[ $response =~ ^([nN][oO]|[nN])$ ]]; then
exit
else
printf '%s\n' "Illegal argument ${response:-empty}" >&2
fi
done
the while read loop should be enough.
The "${response:-empty}" is form of P.E. parameter expansion.
Related
I copied that code to make a THM exercise, I understand it and it does his job that's passing names from a wordlist ($2) to steghide to try to crack the image ($1), and it works, but the problem is that it doesn't show correctly the correct password, it just stops in the word before it, and if you click enter it keeps going, I would like to just stop when it finds it and show me the password, here's the code:
for word in $(cat $2); do
steghide extract -sf $1 -p $word &> /dev/null
if [ $? == 0 ]; then
echo
echo "[!] PWD FOUND - $word [!]"
break
else
echo "NOPE - $word"
fi
done
Steghide was asking me if I wanted to re-write the output file as I already did this process once, so that was the only problem, my script wasn't expecting another input request from steghide.
I wrote this code in a bash script. When I run it, the prompt, "Start? [y/n]", but no matter what I respond, it just closes the window. Also, what is the proper syntax for an if statement.
#echo off
set /p choice="Start? [y/n] "
echo $choice
echo $choice$
if $choice$ == "y"
then
goto Labelyes
fi
if $choice$ == "n"
then
exit
fi
:Labelyes
echo YAY
set /p goodbye="BYE"
if [1==1]; then exit; fi
Thank You!
As commented, the syntax you have used is more like a Microsoft Windows batch (.bat) file than anything else. Below is a conversion to bash. To look at the syntax for read, type help read.
The syntax for an if statement (read man bash or this) is confusing at first. The [[ is actually a command which does pattern matching, and a simple example is shown. The pattern can only be on the right of the =. Note that == can also be used but the standard says to use =.
Simple tests can also use the test command, or [. Arithmetic tests use ((.
goto is a four-letter word and not used in polite circles (some disagree).
#!/usr/bin/env bash
#set /p choice="Start? [y/n] "
read -p "Start? [y/n] " choice
echo "$choice"
#echo $choice$
if [[ $choice = [Yy]* ]] # Accepts y, Y, yes, Yup, etc...
then
#goto Labelyes
echo YAY # Quotes are optional, but beware embedded whitespace
#set /p goodbye="BYE"
read -p "BYE" goodbye
elif [[ $choice == "n" ]] # Only n "elif" means "else if"
then
exit
else
# What happens if neither Y nor N were given?
echo "Invalid response, exiting anyway"
fi
#I have no idea what this is supposed to be for
#if [1==1]; then exit; fi
You could use a case statement instead, but get the if statement understood before trying that.
Bash if statement
Your script is generally incorrect so thinking about why it doesn't work does not make sense.
I am using the following to read a bunch of parameters from the user.
read -p "Name`echo $'\n> '`" NAME
All my parameters have default values. I want to provide an option to the user to skip providing values at any point. i.e. user might provide values for first 3 parameters and press Ctrl+s to skip entering values for the rest of them.
How can I trap Ctrl+s?
Ctrl+S is the terminal scroll lock character, and is not immediately available. You have two options:
Work with the system, use the system standard key combos, and make life easier for yourself and everyone else.
Fight the system, insist on using this key combo, do anything it takes to make it happen, and then live with the consequences.
If you want to work with the system, consider using a blank line and/or Ctrl+D, which is already extensively used to end input. This is easy and robust:
if read -p "Name (or blank for done)"$'\n> ' name && [[ $name ]]
then
echo "User entered $name"
else
echo "User is done entering things"
fi
Alternatively, here's a start for fighting the system:
#!/bin/bash
settings=$(stty -g)
echo "Enter name or ctrl+s to stop:"
stty stop undef # or 'stty raw' to read other control chars
str=""
while IFS= read -r -n 1 c && [[ $c ]]
do
[[ $c = $'\x13' ]] && echo "Ctrl+S pressed" && break
str+="$c"
done
echo "Input was $str"
stty "$settings"
This will correctly end when the user hits Ctrl+S on a standard configuration, but since it doesn't work with the system, it needs additional work to support proper line editing and less common configurations.
Not sure what you mean by trapping. The user can input Ctrl+S by typing Ctrl+V and then Ctrl+S, and your script can then do the check:
if [[ $NAME == '^S' ]]; then
...
# skip asking for more values and continue with default values
fi
I've built my own rpm-packages. After installation, I need some informations from the user via keyboard input, so I've created an post-Script which is working properly if I start it from bash.
In the first step, the script is asking you if a value is correct. If you press Nn you were ask to enter the new one. Here is one example:
while [[ ! ($REPLY =~ ^[NnJjYy]$) ]]
do
read -p "This is just an example, pleaser answer with NnJjYy only" -n 1 -r < $(tty)
if [[ $REPLY =~ ^[Nn]$ ]]
then
printf "\nValue="
read HOST < $(tty)
fi
echo
done
This part is working properly if I run it directly. If I put it on the %post-Part of my SPEC-File, it will run as an endless loop with the errormsg "Mehrdeutige Umlenkung" which should mean "amibigious redirect" in english.
I think the problem is caused by the "$(tty)" of the read command, because if I change this to my active tty (e.g. /dev/pts/0) it's working, but I would like to have it universal.
Do you have any ideas how I could do this?
This program is intended to read a file from stdin and return the longest and shortest lines. Right now it's in an infinite loop.Could someone tell me what I'm doing wrong?
Update: So after reading more about what read does, it's actually right (yay me) but I want to set the delimiter to a newline character while currently the read command is taking a string at every whitespace character. Does anyone know what I can do?
read T
short=""
long=""
for i in $T; do
if [[ $short = "" ]]; then
short=$i
elif [[ ${#i} -lt ${#short} ]]; then
short=$i
elif [[ ${#i} -gt ${#long} ]];then
long=$i
fi
done
echo $short
echo $long
It can't possibly reach an infinite loop, since you are looping over a
necessarily finite variable ($T).
I'm going to assume that your script is "hanging" and assume
one of the possible reasons (to provide you one possible
solution to your classroom problem): that the script is sleeping
waiting for data from stdin and no data is being sent to him.
Here's what you could do:
read short
long=$short
while read line; do
if [[ ${#line} -lt ${#short} ]]; then
short=$line
fi
if [[ ${#line} -gt ${#long} ]]; then
long=$line
fi
done
echo $short
echo $long
Notice that I've first initialized the short and long with the
first line of input, or empty string on stdin's EOF. Then I attempt
to read more lines in a while loop to then check for conditions to update short and
long; it is important to not exclude the line size checks if one
of them applies (like you didn't in your script using elifs).