What exactly is sudo bang bang?
The bang bang (!!
) command is a shortcut to repeat the previous command you entered in your terminal. This command is very useful when you forget that you need admin rights to make a certain action, and lets you repeat it with super-user rights just by typing
sudo !!
instead of typing arrow-up, scrolling to the beginning of the line, adding sudo
and hitting enter (imagine scrolling through those loooong apt-get
commands). So many seconds gained! Yay!
There are many other bang-commands such as !x
, !?x
, !!:p
and !!*
. This blog post lists them and explains what they are for.
What is bang dollar (!$) in Bash?
That's the last argument of the previous command. From the documentation:
!!:$
designates the last argument of the preceding command. This may be shortened to
!$
.
Remark. If you want to play around with Bash's history, I suggest you turn on the shell option histverify
like so:
shopt -s histverify
(you can also put it in your .bashrc
to have it on permanently). When using history substitution, the substitution is not executed immediately; instead, it is put in readline's buffer, waiting for you to press enter… or not!
To make things precise, typing !$
is not equivalent to typing "$_"
: !$
is really a history substitution, refering to the last word of the previous command that was entered, whereas "$_"
is the last argument of the previously executed command. You can compare both (I have shopt -s histverify
):
$ { echo zee; }
zee
$ echo "$_"
zee
$ { echo zee; }
zee
$ echo !$
$ echo }
Also:
$ if true; then echo one; else echo two; fi
one
$ echo "$_"
one
$ if true; then echo one; else echo two; fi
$ echo !$
$ echo fi
And also:
$ echo zee; echo "$_"
zee
zee
$ echo zee2; echo !$
$ echo zee2; echo "$_"
And also
$ echo {1..3}
1 2 3
$ echo "$_"
3
$ echo {1..3}
1 2 3
$ echo !$
$ echo {1..3}
And also
$ echo one ;
$ echo "$_"
one
$ echo one ;
one
$ echo !$
$ echo ;
There are lots of other examples, e.g., with aliases.
How does the vim write with sudo trick work?
In :w !sudo tee %
...
%
means "the current file"
As eugene y pointed out, %
does indeed mean "the current file name", which is passed to tee
so that it knows which file to overwrite.
(In substitution commands, it's slightly different; as :help :%
shows, it's equal to 1,$ (the entire file)
(thanks to @Orafu for pointing out that this does not evaluate to the filename). For example, :%s/foo/bar
means "in the current file, replace occurrences of foo
with bar
." If you highlight some text before typing :s
, you'll see that the highlighted lines take the place of %
as your substitution range.)
:w
isn't updating your file
One confusing part of this trick is that you might think :w
is modifying your file, but it isn't. If you opened and modified file1.txt
, then ran :w file2.txt
, it would be a "save as"; file1.txt
wouldn't be modified, but the current buffer contents would be sent to file2.txt
.
Instead of file2.txt
, you can substitute a shell command to receive the buffer contents. For instance, :w !cat
will just display the contents.
If Vim wasn't run with sudo access, its :w
can't modify a protected file, but if it passes the buffer contents to the shell, a command in the shell can be run with sudo. In this case, we use tee
.
Understanding tee
As for tee
, picture the tee
command as a T-shaped pipe in a normal bash piping situation: it directs output to specified file(s) and also sends it to standard output, which can be captured by the next piped command.
For example, in ps -ax | tee processes.txt | grep 'foo'
, the list of processes will be written to a text file and passed along to grep
.
+-----------+ tee +------------+
| | -------- | |
| ps -ax | -------- | grep 'foo' |
| | || | |
+-----------+ || +------------+
||
+---------------+
| |
| processes.txt |
| |
+---------------+
(Diagram created with Asciiflow.)
See the tee
man page for more info.
Tee as a hack
In the situation your question describes, using tee
is a hack because we're ignoring half of what it does. sudo tee
writes to our file and also sends the buffer contents to standard output, but we ignore standard output. We don't need to pass anything to another piped command in this case; we're just using tee
as an alternate way of writing a file and so that we can call it with sudo
.
Making this trick easy
You can add this to your .vimrc
to make this trick easy-to-use: just type :w!!
.
" Allow saving of files as sudo when I forgot to start vim using sudo.
cmap w!! w !sudo tee > /dev/null %
The > /dev/null
part explicitly throws away the standard output, since, as I said, we don't need to pass anything to another piped command.
cygwin clearscreen from bash
If it's contained in your cygwin install (run Cygwin's setup and make sure you have the package called "ncurses"), try
tput clear
Is it possible to trace my shell(bash, fish, zsh)?
I figured it out though without tracing the fish shell syscalls or something like that I realized that I am using oh-my-fish plugin or framework and it is loading a theme which displayed the unwanted message, thanks for the tips though I at least now know how to trace the fish shell
How do I enable !! in fish?
The fish shell deliberately omits history substitution.
#!/usr/bin/python (sha-bang or she-bang)does not work in bash
The bash documentation is correct: when you enter ./demo.py
at the bash command prompt, bash uses the shebang line to figure out what executable will run the script.
When you do bash demo.py
then of course bash is going to try to run it as a bash script. Because you told it to. (Imagine if you had a bash script with an incorrect shebang line -- how would you run it? By passing it directly to bash, in just this way.)
If you want to start another bash shell which runs your Python script, then use bash -c ./demo.py
to execute demo.py
as a bash command rather than as a bash script. But you shouldn't need to start another shell just to run a Python script.
Using redirection in a linux shell script which run as sudo
I guess, that your script test.sh
does not have a shebang in the first line like this:
#!/bin/bash
Without this line several environment settings affect the way your script is executed. In your case this means that another shell like ash
, ksh
, dash
or whatever will be used to execute the script due to the setting of the root user.
Should I put #! (shebang) in Python scripts, and what form should it take?
The shebang line in any script determines the script's ability to be executed like a standalone executable without typing python
beforehand in the terminal or when double clicking it in a file manager (when configured properly). It isn't necessary but generally put there so when someone sees the file opened in an editor, they immediately know what they're looking at. However, which shebang line you use is important.
Correct usage for (defaults to version 3.latest) Python 3 scripts is:
#!/usr/bin/env python3
Correct usage for (defaults to version 2.latest) Python 2 scripts is:
#!/usr/bin/env python2
The following should not be used (except for the rare case that you are writing code which is compatible with both Python 2.x and 3.x):
#!/usr/bin/env python
The reason for these recommendations, given in PEP 394, is that python
can refer either to python2
or python3
on different systems.
Also, do not use:
#!/usr/local/bin/python
"python may be installed at /usr/bin/python or /bin/python in those
cases, the above #! will fail."
―"#!/usr/bin/env python" vs "#!/usr/local/bin/python"
Related Topics
Prompting for User Input in Assembly Ci20 Seg Fault
Dd: How to Calculate Optimal Blocksize
How to Recompile Just a Single Kernel Module
How to Tell Which Unix Shell I am Using
How to Set Up Autocompletion for Git Commands
How to Create a Waveform Image of an Mp3 in Linux
Mongodb Service Will Not Start After Initial Setup
Installing Openssh on the Alpine Docker Container
Find and Replace in Shell Scripting
Linux "Free -M": Total, Used and Free Memory Values Don't Add Up
Lsb_Release: Command Not Found in Latest Ubuntu Docker Container
Automatic Docker Login Within a Bash Script
X11 Forwarding Request Failed on Channel 0
Elasticsearch Can't Write to Log Files
Should I Rebuild a Dependent Lib After System Update