Can you prevent a command from going into the bash shell command history?
On newer Bash Versions you could simply add a space at the beginning of your command. :)
If it doesn't work by default, add [ \t]* to HISTIGNORE. (As mentioned in the comments. thx)
How do I prevent commands from showing up in Bash history?
If you've set the HISTCONTROL
environment variable to ignoreboth
(which is usually set by default), commands with a leading space character will not be stored in the history (as well as duplicates).
For example:
$ HISTCONTROL=ignoreboth
$ echo test1
$ echo test2
$ history | tail -n2
1015 echo test1
1016 history | tail -n2
Here is what man bash
says:
HISTCONTROL
A colon-separated list of values controlling how commands are saved on the history list. If the list of values includes
ignorespace
, lines which begin with a space character are not saved in the history list. A value ofignoredups
causes lines matching the previous history entry to not be saved. A value ofignoreboth
is shorthand forignorespace
andignoredups
. A value oferasedups
causes all previous lines matching the current line to be removed from the history list before that line is saved. Any value not in the above list is ignored. IfHISTCONTROL
is unset, or does not include a valid value, all lines read by the shell parser are saved on the history list, subject to the value ofHISTIGNORE
. The second and subsequent lines of a multi-line compound command are not tested, and are added to the history regardless of the value ofHISTCONTROL
.
See also:
- Why is bash not storing commands that start with spaces? at unix SE
- Why does bash have a HISTCONTROL=ignorespace option? at unix SE
Avoid adding bash command to history
Use the value ignorespace
in the shell variable HISTCONTROL
, e.g. by setting it in ~/.bashrc
like this.
HISTCONTROL=ignorespace
Now you can prefix the command line with a space, and it will be ignored:
$ export SECRET=sensitive # Intentional blank at the beginning of the line
$ echo $SECRET
From the Bash docs:
HISTCONTROL
A colon-separated list of values controlling how commands are
saved on the history list. If the list of values includes
ignorespace, lines which begin with a space character are not
saved in the history list. A value of ignoredups causes lines
matching the previous history entry to not be saved. A value of
ignoreboth is shorthand for ignorespace and ignoredups. A value
of erasedups causes all previous lines matching the current line
to be removed from the history list before that line is saved.
Any value not in the above list is ignored. If HISTCONTROL is
unset, or does not include a valid value, all lines read by the
shell parser are saved on the history list, subject to the value
of HISTIGNORE. The second and subsequent lines of a multi-line
compound command are not tested, and are added to the history
regardless of the value of HISTCONTROL.
Execute a command without keeping it in history
Start your command with a space and it won't be included in the history.
Be aware that this does require the environment variable $HISTCONTROL
to be set.
Check that the following command returns
ignorespace
orignoreboth
:echo $HISTCONTROL
To add the environment variable if missing, the following line can be added to the Bash profile. E.g., to file
%HOME/.bashrc
.export HISTCONTROL=ignorespace
After sourcing the profile again, space-prefixed commands will not be written to $HISTFILE
.
Sanitising command before storing it in bash history
I'm not sure how foolproof this is; it might miss some way of supplying the -f
option. That said, you can override rm
with the following:
rm () {
local HISTIGNORE="$HISTIGNORE:command rm *"
local arg process
local -a sanitized
command rm "$@"
process=true
for arg in "$@"; do
if [[ $process && $arg = -*f* ]]; then
sanitized+=("${arg//f/}")
elif [[ $arg == -- ]]; then
process=
else
sanitized+=("$arg")
fi
done
history -s rm "${sanitized[@]}"
}
This works as follows:
- Temporarily add the pattern
command rm *
to theHISTIGNORE
list, so that the command about to be executed isn't added to history. - Execute the command as requested.
- Walk through the arguments, looking for any that contain the
-f
option. (Either standalone or in a cluster of short options.) Any such word should have thef
removed. Sanitized words are added to a new array. - The
history -s
command adds the reconstructed command (with sanitized arguments) to the history list.
How to disable editing my history in bash
Here's my own answer, please correct or provide more details if you can.
When the "vi" option is set in bash ("set -o vi" -- "Use a vi-style command line editing interface"), there are two modes of editing a command from history.
The first mode (let's call it "basic") is when you start editing immediately using Backspace, Del and character keys.
The other mode is the "vi mode", entered when you hit Esc.
If you want to keep your history intact, DO NOT use both modes in the same edit. I don't know how bash works exactly, but you can think of it this way:
- Entering the "vi mode" applies any changes done in "basic mode" to the original command, and creates a copy of the command that you can edit further using vi-style commands.
- The changes get applied when you hit Enter (execute), Up, Down or j,k (move to another command in history).
- The changes do not get applied if you hit Ctrl-C.
- Using either basic or vi-style editing ALONE does not affect the original command in history.
When using the terminal history, can I force confirmation when executing dangerous commands from my history?
Use Functions as Command Wrappers
The shell doesn't directly support this feature, in part because a command is stored in history before it is executed. However, you can largely fake it by wrapping your "dangerous" commands in functions that take precedence over the real commands. For example:
rm () {
local regex='[Yy]'
if history | sed '$d' | pcregrep -q "^\s+\d+\s+${FUNCNAME} $*"; then
read -p 'Are you sure? '
[[ "$REPLY" =~ $regex ]] || return 1
fi
command "$FUNCNAME" "$@"
}
The secret sauce is the sed command that strips out the current command that's just been stored in history. Without that, grep would always find the command in the history.
Caveats
- Note the requirement for a grep compiled with PCRE support. You will need to adjust the regular expression if you don't have pcregrep or egrep compiled with PCRE support.
- You might also have to adjust quoting or use eval if word splitting doesn't happen the way you think it should, but it worked fine for me in casual testing. Your mileage may vary.
Related Topics
The Return Code from 'Grep' Is Not as Expected on Linux
Linux Command to Empty All Files of a Directory
How to Communicate with a Linux Kernel Module from User Space Without Littering /Dev with New Nodes
Using Assertion in the Linux Kernel
Determine If There Is Data Left on the Socket and Discard It
How to Find Out What Group a Given User Has
Colors with Unix Command "Watch"
Async Connect and Disconnect with Epoll (Linux)
Call a Kernel Module Function from Program at User Space
How to Tell Cmake I Want My Project to Link Libraries Statically
Extract Tar the Tar.Bz2 File Error
Undefined Reference to 'Clock_Gettime' Although '-Lrt' Is Given
Convert Utf8 to Utf16 Using Iconv
Error: Gdal-Config Not Found While Installing R Dependent Packages Whereas Gdal Is Installed