What does "$-" mean in bash or zsh? [duplicate] - bash

This question already has an answer here:
How can you ask bash for the current options?
(1 answer)
Closed 6 years ago.
Today I found that variable '$-' is a random string, but I don't know what it stands for.
➜ ~ echo $-
569JNRTXZghikms
And I can't change the value:
➜ ~ -='sss'
zsh: command not found: -=sss
➜ ~
And, in a docker it was:
➜ ~ docker run --rm -ti ubuntu
root#7084255fd54e:/# echo $-
himBH
Or:
➜ ~ docker run --rm -ti alpine ash
/ # echo $-
smi
Does it's value related to the system?

$- current options set for the shell.
From the Bash Reference Manual:
Using ‘+’ rather than ‘-’ causes these options to be turned off. The
options can also be used upon invocation of the shell. The current set
of options may be found in $-.
The remaining N arguments are positional parameters and are assigned,
in order, to $1, $2, … $N. The special parameter # is set to N.
The return status is always zero unless an invalid option is supplied.

$- gives you the current options set for the shell.
See the accepted answer from this question for the various other special dollar variables available:
What are the special dollar sign shell variables?

As you are using zsh, run this command:
LESS=+/'PARAMETERS SET BY THE SHELL' man zshparam
to find:
- <S> Flags supplied to the shell on invocation or by the set or setopt commands.
For bash (from Docker), run this command:
LESS=+/'^ *Special Parameters' man bash
To read:
- Expands to the current option flags as specified upon invocation, by the set builtin command, or those set by the shell itself (such as the -i option).

Related

How can I make bash warn undefined variables but still run script?

Is there a way to make bash warn if a variable is undefined but prevent script execution from aborting?
I'm looking for something similar to set -u, except that set -u aborts execution and I would like the script to warn, but continue execution when it finds undefined variables.
I know I can check whether a variable is set , but my scripts have hundred of variables and I'm looking for a solution that avoids checking variables one by one.
You can do it like this:
$ cat /tmp/q.sh
#!/bin/bash
set -u
echo 1
echo $2
echo 3
$ bash --norc --noprofile --noediting -i /tmp/q.sh
1
bash: $2: unbound variable
3
That is, force interactive mode (-i) when running the script, which prevents bash from aborting with set -u, but you have to also use --norc --noprofile --noediting (maybe some things more?), to make it behave more like a non-interactive shell.
I can't tell if this is expected or unexpected behavior, though (it doesn't work when using -c). Works on versions 4.2.46(2)-release (Oracle Linux 7), 4.1.2(1)-release (Oracle Linux 6) and 5.1.16(1)-release (Arch Linux).

Send rm-command with $variable filename via ssh [duplicate]

This question already has answers here:
is it possible to use variables in remote ssh command?
(2 answers)
Closed 4 years ago.
in a bash script i try to do:
ssh -n $username#server2 "rm ${delete_file}"
but always get the error:
rm: missing operand
when I
> echo $delete_file
> /var/www/site/myfile.txt
I get the correct path.
What am i doing wrong?
Could it be that in your case, $delete_file is set on the remote host and not on your current machine?
If you want $delete_file to be expanded on the remote side (i.e., after ssh'ing into server2), you have to use single quotes:
ssh -n $username#server2 'rm ${delete_file}'
Other than that, do you set the value of delete_file in the same script (before ssh'ing), or before invoking your script? If latter is the case, it can't work: Variables are not propagated to scripts called by the current script/session.
You could do the following about it:
delete_file=<your-value> ./ssh-script
or:
delete_file=<your-value>
export delete_file
./ssh-script
As it turns out this last option was the problem, let me elaborate on best practices:
Better than setting environment variables would be the usage of positional parameters.
#!/bin/bash
# $1: file to delete
delete_file=${1:?Missing parameter: which file for deletion?}
ssh -n $username#server2 "rm ${delete_file}"
Usage of the script is now as simple as:
./ssh-script <your-file-for-deletion>
This way, you don't have to remember which variable is exactly expected by the script when calling it - simply call the script with a positional parameter.
As a bonus, the example uses parameter expansion to check for not-set or empty parameters:
delete_file=${1:?Missing parameter: which file for deletion?}
Whenever $1 happens to be unset or empty, the scripts exits immediately with exit code 1 and prints given message to stderr.

Bash, double quotes and "reboot" command

Assume you have those two statements in your bash script:
# No. 1
MSG="Automatic reboot now."
echo $MSG
# No. 2
MSG=""Automatic reboot now.""
echo $MSG
The output of statement number 1 is as expected (it is simply printed). If bash runs statement two, the machine is rebooted (any valid bash command will be executed).
But why?
That's because the meaning of MSG=""Automatic reboot now."" is the following:
Execute reboot now. with the env. var. MSG set to Automatic.
It's equivalent to:
MSG=Automatic reboot now.
A lesser known shell feature is the ability to set environment variables for the duration of a single command. This is done by prepending a command with one or more assignments, as in: var1=foo var2=bar command.
Here's a demonstration. Notice how the original value of $MSG is preserved.
$ export MSG=Hello
$ bash -c 'echo $MSG'
Hello
$ MSG=Goodbye bash -c 'echo $MSG'
Goodbye
$ bash -c 'echo $MSG'
Hello
Now on to your question:
MSG=""Automatic reboot now.""
The pairs of double quotes nullify each other, and might as well not be there. It's equivalent to:
MSG=Automatic reboot now.
which executes reboot with an argument of now. and the $MSG environment variable set to Automatic.

Fish - Get Current Shell Command

I'm trying to get the current shell command (not $history[1] !), specifically i'd like to be able to replace the fish_title - (pwd), with specific running programs i.e. python if I'm in interactive shell, vim etc.
From the documentation:
The first argument to fish_title will contain the most recently executed foreground command as a string, starting with fish 2.2.
So a simple
function fish_title
echo $argv (set -q SSH_CONNECTION; and hostname)":" $PWD
end
should work.
From the documentation, Special Variables
_, the name of the currently running command.
The default fish_title function does this already, does it not?
function fish_title
echo $_ " "
set -q SSH_CONNECTION; and echo (hostname)":"
pwd
end

Difference between $0 and $SHELL

I would like to know the exact difference between $0 and $SHELL. I know that these two are used to know the shell info.
It would be great if some one explain with examples.
What does it indicate if both show different values as below ?
# echo $0
ksh
# echo $SHELL
/sbin/sh
#
SHELL is just an environment variable, while $0 is the path of the currently running program. The user should set SHELL to the value of the preferred shell, similar to the way the user sets PAGER and EDITOR. Any program that needs to spawn a shell should check the value of SHELL to determine which shell to invoke. SHELL is not the path of the shell you get when you login. It will not change when a new shell is run any more than PAGER will change if it is set to less but the user invokes more, or if EDITOR is set to vi and the user runs emacs. For instance:
$ echo $0 $SHELL
bash /bin/bash
$ exec csh
% echo $0 $SHELL
csh /bin/bash
$SHELL gives the full path to your default shell.
$0 gives the name of your current shell.

Resources