Surprise! the shell suggests command line switches
You have discovered Bash's programmable completion feature.
How to enable tab-completion of command line switches in bash?
Take a look at Extended Bash Completion
bash, logic of: a && b && c
You're misunderstanding success/failure statuses and also what &&
and ||
mean in this context in bash.
An exit status of success is 0
, while failure is non-zero so when you say true returns "error" (exit status 1)
, no it doesn't. Also, nothing in shell "returns" anything. Scripts and functions produce output and have an exit status - using the word "return" leads to confusion over which of those 2 separate things you mean. For example if we define this function:
foo() {
echo "hello"
return 7
}
and then use it to populate a variable:
var=$(foo)
$ echo "$var"
hello
did foo()
"return" hello
or did foo()
"return" 7? The best answer is no, it didn't "return" either - it output hello
and exited with status 7
.
Although there's a poorly-named "return" keyword there what that REALLY is producing is an exit status for the function, the same as if you had a shell script that was just:
echo "hello"
exit 7
and you can see that if you test it ($?
always holds the exit status of the most recently run command):
foo() {
echo "hello"
return 7
}
$ foo
hello
$ echo "$?"
7
I assume the shell creators chose "return" for the function keyword because "exit" already meant "exit from the running process" but IMHO that made things confusing, though I don't have a better suggestion and even if I did that ship has sailed long ago. If you read return 7
as set the exit status to 7 then return from the function
without assuming the function is actually "returning" anything then you'd be right.
Note also that the function is outputting "hello" - that's also not a "return" but if you use it as var=$(foo)
then var
ends up containing hello
so then some people incorrectly refer to that as a "return" too since in other languages like C if you wrote var=foo()
:
char *foo() {
return "hello"
}
var=foo()
then var
would contain the argument that was given to return
in the function but that is just not the same semantics as shell where, unlike the similar C code above, var=$(foo)
sets var
to the output from foo()
, not the "return" (actually exit status) from foo()
.
So - the function above doesn't actually "return" anything, it outputs hello
and exits with status 7
.
So here's what your command line true && echo "problem" || echo "exit"
actually does:
true
= output nothing and exit with status 0 (success)echo "problem"
- outputproblem
and exit with status 0 (success)echo "exit"
- outputexit
and exit with status 0 (success)
Now, what do &&
and ||
mean? What they really are is shorthand for if
statements:
&& foo
= if the previously run command exited success then executefoo
|| foo
= if the previously run command exited failure then executefoo
So a command line like:
cmdA && cmdB || cmdC
in terms of success/fail status should be read as:
cmdA
ret=$?
if (( ret == 0 )); then
cmdB
ret=$?
fi
if (( ret != 0 )); then
cmdC
ret=$?
fi
( exit "$ret" )
We need the ret
temp variable because the if
itself has an exit status that'd overwrite $?
. So cmdC
will get called if cmdA
exits with a failure status, but it'll also get called if cmdA
succeeded and then cmdB
exited with a failure status. At the end of cmdA && cmdB || cmdC
the exit status as stored in $?
will simply be the exit status of whichever command ran last, it will not, for example, be the product of boolean arithmetic on all of the exit statuses of all the commands that ran as apparently suggested in the question might be the case.
Note also that what that should NOT be read as is what you may intuitively have expected if you thought of && ... || ...
as a ternary expression, which trips many people up, especially since that ||
is typically an error leg whose incorrect placement may escape your code inspectors/testers notice:
cmdA
if (( $? == 0 )); then
cmdB
else
cmdC
fi
Given the above, here's what your command lines actually mean:
true && echo "problem" || echo "exit"
true
ret=$?
if (( ret == 0 )); then
echo "problem"
ret=$?
fi
if (( ret != 0 )); then
echo "exit"
ret=$?
fi
( exit "$ret" )
true && echo "problem" && echo "exit"
true
ret=$?
if (( ret == 0 )); then
echo "problem"
ret=$?
fi
if (( ret == 0 )); then
echo "exit"
ret=$?
fi
( exit "$ret" )
and if what you WANTED to have happen instead of "2" above was actually:
true
if (( $? == 0 )); then
echo "problem"
else
echo "exit"
fi
then you should write that code or similar instead of using &&
s and ||
s (e.g. as 1 line you could write if true; then echo "problem"; else echo "exit"; fi
) so you don't get unexpected output if you reach the echo "problem"
leg and it fails for some reason thereby causing you to afterwards fall into the echo "exit"
leg (unlikely with just echo
but very possible with other commands).
Bash in Git for Windows: Weirdness when running a command with CMD.exe /C with args
This is actually documented in the ReleaseNotes file (in the top level folder of your installed Git for Windows)
Also, extra care has to be paid to pass Windows programs Windows paths, as they have no clue about MSys style POSIX paths -- You can use something like $(cmd //c echo "$POSIXPATH").
If you use cmd //c echo test
it works as expected.
$ cmd //c echo test
test
The cause is to do with trying to ensure that posix paths end up being passed to the git utilities properly. For this reason, Git for Windows includes a modified MSYS layer that affects command arguments. You should note that it is not intended that the bash shell and tools provided with Git for Windows be used as general purpose unix tools for Windows. If you want a general purpose unix-style toolset then you should install MSYS or cygwin. The Git Bash shell is setup for working with git and sometimes that shows.
Bind a key to accept the first suggested word function in Fish
Yes, the binding is nextd-or-forward-word
. So you could write:
bind \el nextd-or-forward-word
\el
is probably alt-L on your system as well, but you can double check by running fish-key_reader
.
Java command line shell with auto-complete
Check out JReadline and jline2.
Android emulator-5554 offline
In such a case, you can do all of the following in order to be assured that your emulator starts working again :
- Go to cmd and type
adb kill-server
- Go to task manager and find
adb
in processes. If you find one, right click on it and click on end process tree. - In eclipse, go to Window>Android Virtual Device Manager, click on the AVD you want to launch, click on start and uncheck "Launch From Snapshot" and then click on launch.
That's it! It will take a while and it should resolve your problem.
Related Topics
Apache Cgi in User Directory "End of Script Output Before Headers"
How to Curl Using Ipv6 Address
How to Get Errno When Epoll_Wait Returns Epollerr
How to Delete/Remove Certificates from Mono Certificate Stores My and Trust
Can Not Install Software in Linux Error as Dpkg Was Interrupted
Do_Install Error While Running Custom Bitbake in Poky Build
How to Touch a File and Mkdir If Needed in One Line
Execute Bash Script Remotely via Curl
Executing Exe or Bat File on Remote Windows Machine from *Nix
Linux Kernel - How to Get Physical Address (Memory Management)
How to Access Environment Variables Inside .Gdbinit and Inside Gdb Itself
Running Docker on Google Colab
How to Pass Env Variables Between Make Targets
Killing Process in Shell Script