Related
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.
I want to keep ' in a sentence if they are used as i'll, it's etc. however need to remove 'wamp', 'etc'.
I'll say 'bash is great!' if I could do this
should become
I'll say bash is great! if I could do this.
$ perl -pe "s#(?:\s'|'\s)# #g" <<< "I'll say 'bash is great' if I could do this"
I'll say bash is great if I could do this
I remove ' if this character is followed or preceded by a space. Dunno if it fit your needs or not (?!)
Try escaping ' character. Usually in most languages and systems backslash \ is used for escaping special characters.
Try following:
> echo i'll say
i ll say
> echo i\'ll say
i'll say
> echo i\'ll say 'bash' is great
i'll say bash is great
> echo i\'ll say 'bash is great
i'll say bash is great
Using pure bash and parameter expansions:
while IFS= read -r line; do
line="${line//\' / }"
line="${line// \'/ }"
line="${line//\',/,}"
echo "$line"
done < YOUR_BIG_FILE.TXT
I'm writing a bash script which has to pass a variable to another program:
./program $variable
The problem is, it is absolutely necessary for $variable to be passed as a single parameter, which isn't the case if it contains whitespace.
variable=Hello World
./program $variable
-> program receives two arguments: 'Hello' 'World'
Quoting it doesn't do anything at all (well done, bash devs):
variable=Hello World
./program "$variable"
-> program receives: 'Hello' 'World'
Double quoting it does crazy stuff (well done, bash devs):
variable=Hello World
./program "'$variable'"
-> program receives: "'Hello" "World'"
Is there an easy way to do this? Heck, is there a way to do this at all?
Update: Okay, since the problem doesn't seem to be bash, here's some additional info.
The program I'm passing arguments to is a python script. Without modifying the arguments in any way, I get
print sys.argv
-> ['/usr/bin/program', "'Hello", "World'"]
How can I fix that?
Edit: No, I haven't tried
variable="Hello World"
because I never declare $variable. It's not being declared inside my bash function and I'm not allowed to modify it.
Edit: Okay, I got it to work that way.
local temp="$variable"
./program "$temp"
I'd like to know why it works that way and not any other way, though.
did you try with var="hello world"?
i tried this in my solaris box.
> setenv var "hello world"
> cat temp.sh
#!/bin/sh
echo $1
echo $2
> ./temp.sh "$var"
hello world
>
as you can see the $2 is not printed.$var is considered as only one argument.
When you call your script pass the arguments within quotes.
Example script:
#!/bin/bash
for arg in "$#"; do
echo "arg: $1";
shift;
done
When you call it with:
./program "parameter with multiple words" parameter2 parameter3 "another parameter"
The output should be:
arg: parameter with multiple words
arg: parameter2
arg: parameter3
arg: another parameter
Have a look on http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_03_04.html .
The problem is that the expansion of variables is done before of the command line parameters hence your behavior.
You might work it arround with setting IFS to something weird as
IFS='###' V='foo bar baz'; ./program $V
The problem seems to be inside the "program"
variable="Hello World" # quotes are needed because of the space
./program "$variable" # here quotes again
and inside the program
echo "program received $# arguments:"
i=1
for arg in "$#" # again quotes needed
do echo "arg $((i=i+1)): '$arg'" # and again
done
This is almost certainly a problem in the way you are reading the variable in your program.
For instance suppose this is your script (just one line for testing):
echo "$1"
Let's call it echo.sh. If you run echo.sh "test best", you will get test best.
But if your program says
echo $1
you might get behaviour like what you're seeing.
How do I print a newline? This merely prints \n:
$ echo -e "Hello,\nWorld!"
Hello,\nWorld!
Use printf instead:
printf "hello\nworld\n"
printf behaves more consistently across different environments than echo.
Make sure you are in Bash.
$ echo $0
bash
All these four ways work for me:
echo -e "Hello\nworld"
echo -e 'Hello\nworld'
echo Hello$'\n'world
echo Hello ; echo world
echo $'hello\nworld'
prints
hello
world
$'' strings use ANSI C Quoting:
Words of the form $'string' are treated specially. The word expands to string, with backslash-escaped characters replaced as specified by the ANSI C standard.
You could always do echo "".
For example,
echo "Hello,"
echo ""
echo "World!"
On the off chance that someone finds themselves beating their head against the wall trying to figure out why a coworker's script won't print newlines, look out for this:
#!/bin/bash
function GET_RECORDS()
{
echo -e "starting\n the process";
}
echo $(GET_RECORDS);
As in the above, the actual running of the method may itself be wrapped in an echo which supersedes any echos that may be in the method itself. Obviously, I watered this down for brevity. It was not so easy to spot!
You can then inform your comrades that a better way to execute functions would be like so:
#!/bin/bash
function GET_RECORDS()
{
echo -e "starting\n the process";
}
GET_RECORDS;
Simply type
echo
to get a new line
POSIX 7 on echo
http://pubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html
-e is not defined and backslashes are implementation defined:
If the first operand is -n, or if any of the operands contain a <backslash> character, the results are implementation-defined.
unless you have an optional XSI extension.
So I recommend that you should use printf instead, which is well specified:
format operand shall be used as the format string described in XBD File Format Notation [...]
the File Format Notation:
\n <newline> Move the printing position to the start of the next line.
Also keep in mind that Ubuntu 15.10 and most distros implement echo both as:
a Bash built-in: help echo
a standalone executable: which echo
which can lead to some confusion.
str='hello\nworld'
$ echo | sed "i$str"
hello
world
You can also do:
echo "hello
world"
This works both inside a script and from the command line.
On the command line, press Shift+Enter to do the line break inside the string.
This works for me on my macOS and my Ubuntu 18.04 (Bionic Beaver) system.
For only the question asked (not special characters etc) changing only double quotes to single quotes.
echo -e 'Hello,\nWorld!'
Results in:
Hello,
World!
There is a new parameter expansion added in Bash 4.4 that interprets escape sequences:
${parameter#operator} - E operator
The expansion is a string that is the value of parameter with
backslash escape sequences expanded as with the $'…' quoting
mechanism.
$ foo='hello\nworld'
$ echo "${foo#E}"
hello
world
I just use echo without any arguments:
echo "Hello"
echo
echo "World"
To print a new line with echo, use:
echo
or
echo -e '\n'
This could better be done as
x="\n"
echo -ne $x
-e option will interpret backslahes for the escape sequence
-n option will remove the trailing newline in the output
PS: the command echo has an effect of always including a trailing newline in the output so -n is required to turn that thing off (and make it less confusing)
My script:
echo "WARNINGS: $warningsFound WARNINGS FOUND:\n$warningStrings
Output:
WARNING : 2 WARNINGS FOUND:\nWarning, found the following local orphaned signature file:
On my Bash script I was getting mad as you until I've just tried:
echo "WARNING : $warningsFound WARNINGS FOUND:
$warningStrings"
Just hit Enter where you want to insert that jump. The output now is:
WARNING : 2 WARNINGS FOUND:
Warning, found the following local orphaned signature file:
If you're writing scripts and will be echoing newlines as part of other messages several times, a nice cross-platform solution is to put a literal newline in a variable like so:
newline='
'
echo "first line${newline}second line"
echo "Error: example error message n${newline}${usage}" >&2 #requires usage to be defined
If the previous answers don't work, and there is a need to get a return value from their function:
function foo()
{
local v="Dimi";
local s="";
.....
s+="Some message here $v $1\n"
.....
echo $s
}
r=$(foo "my message");
echo -e $r;
Only this trick worked on a Linux system I was working on with this Bash version:
GNU bash, version 2.2.25(1)-release (x86_64-redhat-linux-gnu)
You could also use echo with braces,
$ (echo hello; echo world)
hello
world
This got me there....
outstuff=RESOURCE_GROUP=[$RESOURCE_GROUP]\\nAKS_CLUSTER_NAME=[$AKS_CLUSTER_NAME]\\nREGION_NAME=[$REGION_NAME]\\nVERSION=[$VERSION]\\nSUBNET-ID=[$SUBNET_ID]
printf $outstuff
Yields:
RESOURCE_GROUP=[akswork-rg]
AKS_CLUSTER_NAME=[aksworkshop-804]
REGION_NAME=[eastus]
VERSION=[1.16.7]
SUBNET-ID=[/subscriptions/{subidhere}/resourceGroups/makeakswork-rg/providers/Microsoft.Network/virtualNetworks/aks-vnet/subnets/aks-subnet]
Sometimes you can pass multiple strings separated by a space and it will be interpreted as \n.
For example when using a shell script for multi-line notifcations:
#!/bin/bash
notify-send 'notification success' 'another line' 'time now '`date +"%s"`
With jq:
$ jq -nr '"Hello,\nWorld"'
Hello,
World
Additional solution:
In cases, you have to echo a multiline of the long contents (such as code/ configurations)
For example:
A Bash script to generate codes/ configurations
echo -e,
printf might have some limitation
You can use some special char as a placeholder as a line break (such as ~) and replace it after the file was created using tr:
echo ${content} | tr '~' '\n' > $targetFile
It needs to invoke another program (tr) which should be fine, IMO.
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.