I'm trying to get a user input to loop until the input/name is unique (not contained in output/variable).
I've tried to do something like this, which I thought would have worked:
read -p "$QlabelName" input
while [[ "$input" == "$(/usr/sbin/networksetup -listallnetworkservices |grep "$input")" ]]; do
read -p "Name already in use, please enter a unique name:" input
done
I've also tried putting the $(/usr/sbin/networksetup -listallnetworkservices |grep "$input") bit into a variable itself and then using the condition [[ "$input" == "GREPVARIABLE" ]] without success.
Original user input menu, without loop (working):
labelName=NJDC
QlabelName=$(echo Please enter the name of connection to be displayed from within the GUI [$labelName]: )
read -p "$QlabelName" input
labelName="${input:-$labelName}"
echo "The connection name will be set to: '$labelName'"
I've tried a variety of solutions from SO, Unix, ServerFault, etc with no success. I've tried if, while, until, !=, ==, =~ as well with no success.
I've confirmed with simple debug echo's at each step that variables contain the data, but the loop is not working.
EDIT (solution, in context to the question, thanks to #LinuxDisciple's answer):
labelName=NJDC
QlabelName=$(echo Please enter the name of connection to be displayed from within the GUI [$labelName]: )
read -p "$QlabelName" input
while /usr/sbin/networksetup -listallnetworkservices |grep -q "^${input}$"; do
read -p "Name already in use, please enter a unique name:" input
done
labelName="${input:-$labelName}"
echo "The connection name will be set to: '$labelName'"
This was important to me to keep default variable values for labelName and output the correct information to the user.
read -p "$QlabelName" input
while /usr/sbin/networksetup -listallnetworkservices |grep -q "^${input}$"; do
read -p "Name already in use, please enter a unique name:" input
done
grep's return code is good enough for while, and since we don't want to actually see the output, we can use -q to suppress it. You can also run it without -q to see what grep actually found until you're satisfied that it's running correctly.
For further debuggability, I would pipe the output to cat -A. You can echo your variable value in the while-loop and just add |cat -A immediately after the done and it should show all the characters:
read -p "$QlabelName" input
while /usr/sbin/networksetup -listallnetworkservices |grep -q "^${input}$"; do
read -p "Name already in use, please enter a unique name:" input
echo "Input was:'$input'"
done |cat -A
Related
I'm trying to interpret this block of code. Searched google to see what these commands mean and no luck. I put my interpretation of what each line/block means to me. If I am wrong, please correct me. I am new to unix commands. Code:
#!/bin/bash
# input 1st command line argument for the version.
export VERSION=$1
# if user didn't input a version, print the echo message and exit (not sure what -n means but I am assuming)
if [[ ! -n "$VERSION" ]]; then
echo "Missing Version"
exit 1
fi
# creating variable UNAME that tells who the person is (their name)
export UNAME='whoami'
# no idea what -s and -p mean but i think this prints the message "enter password for $UNAME" and stores it in a new variable named PASSWORD. the $UNAME will print whatever whoami said.
read -s -p "Enter password for $UNAME: " PASSWORD
echo ""
The -p flag issues a prompt before reading input into a variable
The -s flag stop the typed response from being shown (i.e. for a sensitive password)
More information is available here:
https://linuxhint.com/bash_read_command/
-p
prompt output the string PROMPT without a trailing newline before
attempting to read.
-s
do not echo input coming from a terminal.
I'm very new to bash scripting and here's what i'm trying to do:
1 - Read a file - this file is a list of names
2 - Ask user if they want to delete {name}
3 - If user enters y, proceed
This is what my script looks so far:
while IFS= read -r repo
do
read -p "Do you want to delete $repo" ip
echo $ip
if [ "$ip" == "y" ]
then
#do something
fi
done < "$filename"
The read -p line does not wait for a user prompt. I sort of understood what/where the problem is and I was trying to resolve it by reading up on this link - https://bash.cyberciti.biz/guide/Reads_from_the_file_descriptor_(fd)
But somehow I was unable to resolve this issue. What am I doing wrong? Please help!
Use a different file descriptor for the named file. You know where that data is coming from; you don't know where standard input might be redirected from, so leave it alone.
while IFS= read -r -u 3 repo # Read from file descriptor 3
do
read -p "Do you want to delete $repo" ip # Read from whatever standard input happens to be
echo "$ip"
if [ "$ip" = "y" ]
then
#do something
fi
done 3< "$filename" # Supply $filename on file descriptor 3
-u is bash-specific, but I note you are already using another bash-specific feature, the -p option to read. The POSIX way to read from something other than standard input is IFS= read -r repo <&3 (which says, copy file descriptor 3 onto standard input for this command).
See this question:
Does bash support doing a read nested within a read loop?
Essentially, you're reading in the file through standard input which is the same input stream as when you type, so when you prompt the user, the script is treating the file's input as the user's input. If you instead read in the the file on another input stream then it wouldn't override.
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?
I have a list of users in a text file. I need to query our campus Active Directory to make sure these users are still "active" users (my machines are not part of the campus AD). The list of users is mapped to a number of identical attributes on the AD (name, cn, sAMAccountName, uid, gecos). I can successfully query the AD with ldapsearch for individual users, so what I am trying to figure out is:
a) how to use the file as input for the query
b) how to construct a shell script so the query will go line by line, and then output any "non-active" users so i can email it for notification.
Any help is much appreciated.
Something you could try to accomplish what you desire would be:
emailFile="/var/tmp/emailFile.txt"
for i in $(cat ${filename}) ; do
results=$(*INPUT LDAPSEARCH HERE REPLACING USERNAME WITH ${i}* | grep -i lastlogontimestamp)
if [[ ${results} != "" ]] ; then
echo "${i} appears to be an active user"
else
echo "${i} IS INACTIVE"
echo "${i}" >> "${emailFile}"
fi
done
This is NOT a working script, but this should give you a very good idea of how to get this to work in your environment. Couple things to note...
${filename} = location/filename of your list of names
INPUT LDAPSEARCH HERE REPLACING USERNAME WITH ${i} = You would enter in your command to run an ldap search here.
example $(ldapsearch -D "cn=manager" -w password -h server.example.com -b "dc=example,dc=com" "cn=${i}" | grep -i "lastlogontimestamp")
"lastlogontimestamp" would be equal to what part of the query you want to examine to determine if the user is active or not.
This would set the ${results} variable to a string you are looking for. This could be a datestamp or empty if users have never logged in.
The next "if" statement, would compare the results to a string/pattern you are expecting. My if statement above, states that if ${results} is not equal to nothing, then inform you that the user you searched is active. If the ${results} are indeed empty, then log the username.
You will have to modify the ldapsearch portion to fit your needs, and the if statement to match what you are expecting to see from your query if the user is not active. I hope this helps.
To answer you question you provided in the comments...
You could use nested if expressions. Example.
if [[ $(some command) = "Some expected result" ]] ; then
if [[ ${results} != "" ]] ; then
echo "${i} appears to be an active user"
else
echo "${i} IS INACTIVE"
echo "${i}" >> "${emailFile}"
fi
fi
done
You could add a second variable where you run a command in the for loop such as
userExists=$(some ldapsearch command to see if user exists)
results=$(*INPUT LDAPSEARCH HERE REPLACING USERNAME WITH ${i}* | grep -i lastlogontimestamp
if [[ ${userExists} = "Some expected result" ]] ; then
if [[ ${results} != "" ]] ; then
You also asked a question about using "grep" to look for more than one item. Example is below.
grep "514\|546"
Example 2.
Lets say I have a file called test.txt with 5 lines
one
two
three
four
five
I would run the following command to look inside the file to find "two" and "three"
cat test.txt | grep "two\|three"
I have the following snippet in a bash script written in Solaris 10:
printf "port(389)="
read PORT
if [[ $PORT == "" ]]; then
PORT=389
fi
What I am trying to get that if the user hits the enter key, the Port should be set to 389.
The snippet above does not seem to be working.
Any suggestions?
This prompts the user for input and if enter is pressed by itself, sets the value of port to a default of "389":
read -rp "port(389)=" port
port="${port:-389}"
It's not exactly what you asked, but Solaris has a set of utilities for this sort of thing.
PORT=`/usr/bin/ckint -d 389 -p 'port(389)=' -h 'Enter a port number'`
Check out the other /usr/bin/ck* utilities to prompt the user for other types of data, including things like files or user names.
If you pass -e to read then you can use -i to specify an initial value for the prompt.
If the user enters nothing then $PORT is replaced with nothing - the ancient convention for making this work with the original Bourne shell is:
if [ "x$PORT" == "x" ]; then
Though more modern shells (i.e. actual bash, but not Solaris 10 /bin/sh which is
an ancient Bourne shell) should be able to deal with:
if [[ "$PORT" == "" ]]; then
or even
if [[ -z "$PORT" ]]; then
Another way with just the shell
-- try parameter substitution:
read port
port=${port:-389}