How to solve Linux If-Else statement syntax error? - linux

I am trying to check whether a directory already exists or not inside a case-control statement. But it is giving an error in 'then' statement.
case $choice in
1)echo "Enter directory name: "
read dname
mkdir $dname
if[-d "$dname"]
then
echo "$dname directory already exists."
else
echo "$dname directory successfully created."
fi
read
;;
error message:
uan.sh: line 13: syntax error near unexpected token `then'
uan.sh: line 13: ` then'

The parser is seeing then outside of an if statement, because you don't have the keyword if in a command position. You have the word if[-d which the parser accepts as an ordinary command name; the parser doesn't know or care whether the command actually exists or not.
Whitespace is important:
if [ -d "$dname" ]
The brackets are supposed to remind you of syntax, but have probably caused more trouble than they have ever saved. [ is the command, and it requires ] as its final argument. Using the name test is much simpler and doesn't lull you into thinking the brackets are somehow special to the parser:
if test -d "$dname"

Related

Getting "ambiguous redirect" error in my shell script [duplicate]

The following line in my Bash script
echo $AAAA" "$DDDD" "$MOL_TAG >> ${OUPUT_RESULTS}
gives me this error:
line 46: ${OUPUT_RESULTS}: ambiguous redirect
Why?
Bash can be pretty obtuse sometimes.
The following commands all return different error messages for basically the same error:
$ echo hello >
bash: syntax error near unexpected token `newline`
$ echo hello > ${NONEXISTENT}
bash: ${NONEXISTENT}: ambiguous redirect
$ echo hello > "${NONEXISTENT}"
bash: : No such file or directory
Adding quotes around the variable seems to be a good way to deal with the "ambiguous redirect" message: You tend to get a better message when you've made a typing mistake -- and when the error is due to spaces in the filename, using quotes is the fix.
Do you have a variable named OUPUT_RESULTS or is it the more likely OUTPUT_RESULTS?
michael#isolde:~/junk$ ABC=junk.txt
michael#isolde:~/junk$ echo "Booger" > $ABC
michael#isolde:~/junk$ echo "Booger" >> $ABB
bash: $ABB: ambiguous redirect
michael#isolde:~/junk$
put quotes around your variable. If it happens to have spaces, it will give you "ambiguous redirect" as well. also check your spelling
echo $AAAA" "$DDDD" "$MOL_TAG >> "${OUPUT_RESULTS}"
eg of ambiguous redirect
$ var="file with spaces"
$ echo $AAAA" "$DDDD" "$MOL_TAG >> ${var}
bash: ${var}: ambiguous redirect
$ echo $AAAA" "$DDDD" "$MOL_TAG >> "${var}"
$ cat file\ with\ spaces
aaaa dddd mol_tag
I've recently found that blanks in the name of the redirect file will cause the "ambiguous redirect" message.
For example if you redirect to application$(date +%Y%m%d%k%M%S).log and you specify the wrong formatting characters, the redirect will fail before 10 AM for example. If however, you used application$(date +%Y%m%d%H%M%S).log it would succeed. This is because the %k format yields ' 9' for 9AM where %H yields '09' for 9AM.
echo $(date +%Y%m%d%k%M%S) gives 20140626 95138
echo $(date +%Y%m%d%H%M%S) gives 20140626095138
The erroneous date might give something like:
echo "a" > myapp20140626 95138.log
where the following is what would be desired:
echo "a" > myapp20140626095138.log
Does the path specified in ${OUPUT_RESULTS} contain any whitespace characters? If so, you may want to consider using ... >> "${OUPUT_RESULTS}" (using quotes).
(You may also want to consider renaming your variable to ${OUTPUT_RESULTS})
If your script's redirect contains a variable, and the script body defines that variable in a section enclosed by parenthesis, you will get the "ambiguous redirect" error. Here's a reproducible example:
vim a.sh to create the script
edit script to contain (logit="/home/ubuntu/test.log" && echo "a") >> ${logit}
chmod +x a.sh to make it executable
a.sh
If you do this, you will get "/home/ubuntu/a.sh: line 1: $logit: ambiguous redirect". This is because
"Placing a list of commands between parentheses causes a subshell to
be created, and each of the commands in list to be executed in that
subshell, without removing non-exported variables. Since the list is
executed in a subshell, variable assignments do not remain in effect
after the subshell completes."
From Using parenthesis to group and expand expressions
To correct this, you can modify the script in step 2 to define the variable outside the parenthesis: logit="/home/ubuntu/test.log" && (echo "a") >> $logit
I got this error when trying to use brace expansion to write output to multiple files.
for example: echo "text" > {f1,f2}.txt results in -bash: {f1,f2}.txt: ambiguous redirect
In this case, use tee to output to multiple files:
echo "text" | tee {f1,f2,...,fn}.txt 1>/dev/null
the 1>/dev/null will prevent the text from being written to stdout
If you want to append to the file(s) use tee -a
If you are here trying to debug this "ambiguous redirect" error with GitHub Actions. I highly suggest trying it this way:
echo "MY_VAR=foobar" >> $GITHUB_ENV
The behavior I experienced with $GITHUB_ENV is that, it adds it to the pipeline environment variables as my example shows MY_VAR
I just had this error in a bash script. The issue was an accidental \ at the end of the previous line that was giving an error.
One other thing that can cause "ambiguous redirect" is \t \n \r in the variable name you are writing too
Maybe not \n\r? But err on the side of caution
Try this
echo "a" > ${output_name//[$'\t\n\r']}
I got hit with this one while parsing HTML, Tabs \t at the beginning of the line.
This might be the case too.
you have not specified the file in a variable and redirecting output to it, then bash will throw this error.
files=`ls`
out_file = /path/to/output_file.t
for i in `echo "$files"`;
do
content=`cat $i`
echo "${content} ${i}" >> ${out_file}
done
out_file variable is not set up correctly so keep an eye on this too.
BTW this code is printing all the content and its filename on the console.
if you are using a variable name in the shell command, you must concatenate it with + sign.
for example :
if you have two files, and you are not going to hard code the file name, instead you want to use the variable name
"input.txt" = x
"output.txt" = y
then ('shell command within quotes' + x > + y)
it will work this way especially if you are using this inside a python program with os.system command probably
In my case, this was a helpful warning, because the target variable (not the file) was misspelled and did not exist.
echo "ja" >> $doesNotExist
resulting in
./howdy.sh: line 4: $doesNotExist: ambiguous redirect
For my case, if I specify the output file via a env (e.g $ENV_OF_LOG_FILE), then will get the error ambiguous redirect.
But, if I use plain text as file path (e.g /path/to/log_file), then there is no error.

Can't populate variable from command in Bash

I'm new to bash scripting, and I'm working on a script where the user enters a username and gets a list of the associated information from /etc/passwd. Unfortunately, I seem to be having trouble populating a variable from a command. The error message I'm getting suggests the if statement isn't being entered into, but I'm not sure why.
The script currently looks like this:
#!/bin/bash
#readifs
FILE=/etc/passwd
read -p "Enter a username > " user_name
file_info=$(grep "^$user_name:" $FILE)
if [ -n "$file_info" ]; then
IFS=":" read user pw uid gid name home shell <<< "$file_info"
echo "User = '$user'"
echo "UID = '$UID'"
echo "GID = '$GID'"
echo "Full Name = '$name'"
echo "Shell = '$shell'"
else
echo "No such user '$user_name'" > &2
exit 1
fi
When I run it, using a valid username, I get the following two lines:
readifs.sh: line 20: syntax error near unexpected token `&'
readifs.sh: line 20: ` echo "No such user '$user_name'" > &2'
I'm pretty sure I'm missing something obvious, or doing something bash doesn't allow but I'm too new to catch. Can anyone point out and correct the error in my script?
Thank you to Charles Duffy for all the great feedback on not just this script, but bash scripting and Stack Overflow in general.
I was able to fix the script as I wanted. I removed the ^ and : from the file_info line, which was stopping the grep command from finding the line I wanted. I also renamed $UID and $GID to use lower case letters, and removed the space in "> &2".
Thank you again for your assistance.

BASH Syntax Checking Debug Mode Malfunction?

We can use bash -n script.sh to validate the syntax of a shell script. However, when I was trying to test this function, I noticed not all the syntax errors could be found by this option.
For example:
root#ubuntu:~/testenv# cat test
#!/bin/bash
SEND=1
if [ "$SEND" -eq 0 ]
echo no
fi
Now, let's test the script:
root#ubuntu:~/testenv# bash -n test
test: line 5: syntax error near unexpected token `fi'
test: line 5: `fi'
It works fine. However, if I just remove one of the bracket:
root#ubuntu:~/testenv# cat test
#!/bin/bash
SEND=1
if [ "$SEND" -eq 0
then
echo no
fi
root#ubuntu:~/testenv# bash -n test
root#ubuntu:~/testenv#
Nothing happened!
I also checked the man page of bash, it describes the "-n" is:
-n Read commands but do not execute them. This may be used to check a
shell script for syntax errors. This is ignored by interactive
shells.
It is a script file, so it shouldn't be an "interactive shell" right? So,how could this happen?
I'm guessing you have run into a very strange quirk of the way the shell implements single-bracketed conditionals: [ is a command, not a special character. Look in your system executable directory (probably /usr/bin) and you will find an executable file literally named [ which implements this command. When you write something like
[ "$SEND" -eq 0 ]
then you're actually invoking the command [ with four arguments:
The value of $SEND
The string -eq
The string 0
The string ]
The command [ checks that the last argument is ] (because it would look weird otherwise), then puts the remaining arguments together to form a condition and return the result of testing the condition.
Now, because [ is a command, it's not a syntax error to invoke that command with any set of arguments you like. Sure, if you leave off the trailing ], you will get an error, but that error comes from the command [, not from the shell. That means you have to actually run the script to get the error - the syntax checker won't see anything wrong with it. As far as bash is concerned, [ is just a command name, no different from, say, my_custom_conditional_test, and if you were to write
my_custom_conditional_test "$SEND" -eq 0
it would be obvious that this is fine, right? Bash thinks of [ the same way.
I should note that for efficiency, bash doesn't actually use the executable file /usr/bin/[; it has its own builtin implementation of [. But people expect [ to act the same way regardless of whether it's built in to the shell or not, so the Bash syntax checker can't give its own [ special treatment. Since it wouldn't be a syntax error to invoke /usr/bin/[ with no trailing ], it can't be a syntax error to invoke the builtin [ without a ].
You can contrast this with [[, which does more or less the same thing (testing a condition) but is given special meaning by the shell. [[ is a special token in shell syntax, not a command. If you write [[ instead of [, and you omit the corresponding trailing ]], you bet Bash is going to complain about a syntax error.

case in bash: "line 4: syntax error near unexpected token `)'"

case in bash:
line 4: syntax error near unexpected token `)'
I'm trying to use the command case in Bash (on my Raspberry Pi again), but when I run my script, Bash spits out errors. I've read over many tutorials and I think I'm doing the same thing as them, but something's just not right.
Here's my code:
#!/bin/bash
case "$1" in
help) echo "You asked for help. Sorry, I'm busy."
*) echo "You didn't say anything. Try 'help' as the first argument."
esac
Here's the output (the filename is newmkdir and I ran it with no arguments):
./newmkdir: line 4: syntax error near unexpected token `)'
./newmkdir: line 4: ` *) echo "You didn't say anything. Try 'help' as the first argument."'
I'm trying to have my script interpret help and then make anything else output the next line.
(Note this is just an example of a glitched script. This script has no meaning and might not even make sense, it's just a test.)
You are missing ;; at the end of each pattern:
#!/bin/bash
case "$1" in
help)
echo "You asked for help. Sorry, I'm busy."
;;
*)
echo "You didn't say anything. Try 'help' as the first argument."
;;
esac
Think of it as a break statement in a programming language. They are compulsory on case.

Shell programming error [duplicate]

This question already has answers here:
Syntax error near unexpected token 'then'
(2 answers)
Closed 7 years ago.
I'm new to shell programming and I'm supposed to do this
Create two directories OS_filesR and OS_filesW on Desktop
Ask the user to enter file name.
Create file with the entered file name in OS_filesR if this is the Odd Creation and
remove readable permission.
If this is the even Creation, Create the file in OS_filesW and remove writable
permission.
Ask user if he/she wants to create another file if yes repeat steps (2, 3), if no
exist.
Here is the code:
mkdir /home/karim/Desktop/OS_filesR /home/karim/Desktop/OS_filesW
counter=0
while(1)
do
echo "Enter the file name"
read var
if[$counter % 2 -eq 0]
then
touch /home/karim/Desktop/OS_filesW/$var
chmod -w $var
else
touch /home/karim/Desktop/OS_filesR/$var
chmod -r $var
fi
echo "Do you want to create another file? Enter yes or no"
read var2
if[$var2 != "yes"]
then
break
fi
counter++
done
I keep getting this error:
line 9: syntax error near unexpected token then'
line 9: then'
So how can I fix this?
Place a space after the "[" on line 9. "[" is just an alias for the test command, and is not parsed separately from the rest of the string without the space.

Resources