So yeah, this is an old topic, but none of these questions answered it for me so I just spent ages trying to figure this out too!
Here's My solution with thanks from @Gilles for the hint of using 'fc -R' and 'fc -W' :).
Paste the script below this into your .zshrc file.
reload with source .zshrc
then type 'forget' to forget the last command :D. type 'forget 3' to forget the last 3 commands. Some sexy shizz.
Pressing the up arrow will take you straight to the last command and won't remember the word 'forget' either :).
Updated: Added home path, so it works in all directories now lol.
Update 2: Added the ability to pass the number of last commands you want to forget :D. Try 'forget 2' to forget the last 2 commands :D.
# Put a space at the start of a command to make sure it doesn't get added to the history.
setopt histignorespace
alias forget=' my_remove_last_history_entry' # Added a space in 'my_remove_last_history_entry' so that zsh forgets the 'forget' command :).
# ZSH's history is different from bash,
# so here's my fucntion to remove
# the last item from history.
my_remove_last_history_entry() {
# This sub-function checks if the argument passed is a number.
# Thanks to @yabt on stackoverflow for this :).
is_int() ( return $(test "$@" -eq "$@" > /dev/null 2>&1); )
# Set history file's location
history_file="${HOME}/.zsh_history"
history_temp_file="${history_file}.tmp"
line_cout=$(wc -l $history_file)
# Check if the user passed a number,
# so we can delete x lines from history.
lines_to_remove=1
if [ $# -eq 0 ]; then
# No arguments supplied, so set to one.
lines_to_remove=1
else
# An argument passed. Check if it's a number.
if $(is_int "${1}"); then
lines_to_remove="$1"
else
echo "Unknown argument passed. Exiting..."
return
fi
fi
# Make the number negative, since head -n needs to be negative.
lines_to_remove="-${lines_to_remove}"
fc -W # write current shell's history to the history file.
# Get the files contents minus the last entry(head -n -1 does that)
#cat $history_file | head -n -1 &> $history_temp_file
cat $history_file | head -n "${lines_to_remove}" &> $history_temp_file
mv "$history_temp_file" "$history_file"
fc -R # read history file.
}
So there's a few things going on here.
This command will let us type a space before any command, and it'll not be added to history.
setopt histignorespace
So we can press the space bar, and type 'echo hi', press enter and when we press the up arrow, 'echo hi' is not in our history :).
Notice how the alias 'forget' has a space before my_remove_last_history_entry. This is so that zsh doesn't save our 'forget' to history.
The function explained
ZSH uses fc for the history or something, so we do 'fc -W' to write our current commands to the history file, them we use 'head -n -1' to trim the last command off the file. We save that output to a temporary file and then replace the original history file with the temp one. And finally reload the history with fc -R.
There is however a problem with the function which is fixed with the alias.
If we run the function by it's name, it'll remove the last command, which is the call to the function. This is why we use the alias with a call to it using a space, so that zsh doesn't add this function name to the history file, making the last entry the one we want :D.
~.zsh_history
by typingopen ~/.zsh_history
, and then just delete the desired line. In Linux, you could probably do the same thing but "replaceopen
with the name of your preferred text editor, such asnano
,vim
, orgedit
." (Answer modified from Pot '16.)