iTerm2 get previous DIFFERENT command using up and down arrow keys - macos

I found it irritating that if you run one command 5 times you have to press the arrow key 6 times to get the previous command. Is it some way to change this behavior?
iTerm2 Build 1.0.0.20111020

That's not a feature of iTerm but of your shell's history feature. If you use the default Bash you can put this into your ~/.bashrc:
export HISTCONTROL=ignoreboth
shopt -s histappend
# After each command, save and reload history
export PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND"
The first line will tell Bash to ignore duplicated and empty history entries. The second line will merge the history of multiple open sessions (e.g. in multiple tabs or windows). The thirs line will make sure that the history is preserved after each command.

Related

aliases are not stored in zsh history

Whenever I execute a command using an alias, this command is not stored in the shell's command history.
So if I run history these commands do not appear in the list.
Nor do they appear when I press CTRL + r for reverse searching the command history.
When I press the keyboard's arrow up for scrolling through the last commands, I will see an aliased command only if it was the last command I ran. Other aliased commands are will not be displayed.
For example:
$ cd my-repo
$ gs # an alias to git status
$ history
Outputs the following:
2374 cd my-repo
(the gs command is not displayed)
A few notes:
gs is only an example. The issue is far more annoying in more complex commands since I have to retype them all over again instead of executing them from history (e.g. k get pods | grep <pod_name>, where k=kubectl).
gs is defined so: alias gs=' git status'.
I also have a few functions in ~/.alias, e.g.:
mkcd () {
mkdir -pv $1
For some reason, mkcd (or any other function in the alias file) is included in the history.
I do not mind if it prints out gs or expands to git status, I'll take any of the two...
I am using zsh with oh-my-zsh on macOS (Monterey). My shell aliases are defined in ~/.alias which is sourced in ~/.zshrc (source ~/.alias).
This happens both in iTerm2 and in the default Mac terminal.
Thank you for taking the time to help :-)
I will assume that your example alias is exactly what you have in your ~/.alias file.
So you have aliases like this (notice the space character in front of git command):
alias gs=' git status'
There is an shell option called HIST_IGNORE_SPACE which is doing exactly what you are experiencing - in short it will not add command to the history when it starts with space character. Example:
echo 'This command will make it to the history.'
echo 'This poor command will be forgotten.'
You can check your current options using setopt or specifically:
setopt | grep 'histignorespace'
So there are two ways how you can fix this - either by fixing your aliases to not start with space or, If you really don't want this functionality at all, by unsetting it in your ~/.zshrc like this:
unsetopt HIST_IGNORE_SPACE

Searching your command history on macOS terminal

What is the shortcut to search my command history in macOS terminal?
For how long is the history available for searching? Where is it stored?
How about using Ctrl+R for searching on the Terminal Utility in Mac for searching on the command history,
dudeOnMac: freddy$ whoami
freddy
(reverse-i-search)`who': whoami
Well for controlling how long the history would be retained that depends on a few shell environment variables, HISTFILESIZE which is nothing but number of lines of history you want to retain. Set a huge value for it in .bash_profile for it to take effect
HISTFILESIZE=10000000
Use Ctrl + R for searching a command from history in Terminal.
(reverse-i-search)`':
Type any substring of the command you want to search e.g. grep
(reverse-i-search)`grep': grep "XYZ" abc.txt
It will return the latest command that matches your input. If that is not the command you were searching for, keep pressing Ctrl + R for next match until you find your command.
Once you found your command press Return to execute it.
If you want to exit without running any command, press Ctrl + G
PS: This answer is same as suggested by Inian, just giving more details for easy usage.
The command history is stored under your home folder in a hidden file called .bash_history. To view it's content in nano, use the following command in Terminal:
nano ~/.bash_history
Or open with your text editor (default is TextEdit):
open ~/.bash_history
In my case it's a very long list and as I scroll through seems like the last ~500 command is stored here.
Migrating an answer to SO from this answer on the Unix and Linux Stack Exchange:
Pressing ctrl+R will open the history-search-backward. Now start typing your command, this will give the first match. By pressing ctrl+R again (and again) you can cycle through the history.
If you like to be super lazy you can bind the up/down arrow keys to perform this search, I have the following in my .inputrc to bind the up/down arrow key to history-search-backward and history-search-forward:
# Key bindings, up/down arrow searches through history
"\e[A": history-search-backward
"\e[B": history-search-forward
"\eOA": history-search-backward
"\eOB": history-search-forward
Just type something (optional), then press up/down arrow key to search through history for commands that begin with what you typed.
To do this in .bashrc rather than .inputrc, you can use:
bind '"\e[A": history-search-backward'
Use this command -
history
This works on both OSX and Linux.
History is stored in ~/.zsh_history or ~/.bash_history or ~/.history depending on your shell.
History is stored for 1000 or 2000 lines depending on your system.
echo $HISTSIZE
You can also try the following:
history | grep 'git'
Where 'git' is the command you are looking for.
For those who want to search specific command from history, you can do so with reverse-i-search. Reverse search allow you to type in any key words(any) that is part of the command you are looking for and reverse search navigate back to history, match previous commands incrementally and return the entire command.
It is especially useful as when one cannot remember all handy lengthy commands they use often. To do reverse-search ctrl + R and type any clue you have and that will return your previous commands matching the words you type. Then once found the command, hit Enter to execute it directly from search.
Automation AppleScript
Since you mentioned viewing your history as a quick solution, via the Terminal.app. You might want to automate, or quickly view history, maybe from the dock. You may use the AppleScript application as one alternative. This is an optional approach to create a simple shortcut, as to many others.
Open the AppleScript editor application.
Add your specified commands, for history.
Code
tell application "Terminal"
do script "history"
end tell
Save as application, drag to dock for convenience.
History Storage & Time Stored Details
HISTSIZE Determines how many lines will be written to the history file.
HISTFILESIZE Determines how long the file.
Find out how long history is stored:
echo $HISTSIZE $HISTFILESIZE
Note: You may also increase your command history storage size in the length of two variables. You may achieve this through HISTSIZE and HISTFILESIZE environment variables which are located in your ~/.bash_profile file.
It is possible to achieve this by modifying ~/.bash_profile, the number placeholder with SIZE represent's the number, lines value as example:
export HISTFILESIZE=SIZE # Example 1000
export HISTSIZE=SIZE # Example 10000
Pre macOS 11 Big Sur
cat ~/.bash_history
HISTFILESIZE will only set a maximum history value which is stored to the history file when a session is started. HISTSIZE will determine specifically how many lines will be stored or in other words, written at the end of the session. If the set HISTFILESIZE is determined to be a large value than what HISTSIZE is set, you will not view history larger than your set HISTSIZE. The reason is that the history file is overwritten with the HISTSIZE unless using histappend option turned ON.
You may use also histappend to append history, If the histappend shell option is turned on lines are appended to the history file. Otherwise, the overwritten alternative proceeds.
Bash GNU - histappend
macOS 11 Big Sur
nano ~/.zprofile
Modify history environment variables, set to a value:
export HISTFILESIZE=1000
export HISTSIZE=SIZE=1000
Run the source command can be used to load any functions file into the current shell script or a command prompt.
source ~/.zprofile
echo $HISTSIZE $HISTFILESIZE
Outputs:
1000 1000
Output where some history is stored:
cat ~/.zsh_history
For macOS Big Sur the file is now .zsh_history
If you do vi ~/.zsh_history in the terminal you can use regex by pressing the / and then the search term.
To review or recall recently used commands, you can just press the up arrow key to sequentially read back through the history stored in .bash_history.
To search through history with ease, I advise you to install fzf.
It's an interactive Unix filter for command-line that can be used with any list; files, command history, processes, hostnames, bookmarks, git commits, etc.
Just install it, click ctrl + R, and you'll be to scroll through you shell history, without the need to grep or waiting ages until the command you're waiting for pops up.
It supports Mac OS, Linux and even Windows.
# USAGE: find.history cd
# filter commands in shell history by a search term and execute the selected command
function find.history {
eval $(history | grep "$1" | tail | awk '{$1=""}1' | tail -r | peco)
}
You will need to have peco installed.
https://github.com/peco/peco
[$]> brew install peco

How to mark the start of the shell session from Vim?

When I am using vim-figitive it often shells out for commands like git push and so on.
Every time it opens a shell I see some leftovers from the previous session, something like:
Press ENTER or type command to continue
It sets me off every time because I can't figure out if this is the output from the current session or the previous one.
Is there a way to mark it with some sort of line every time I shell out from vim? Something like this in .zshrc would do it I think:
if [ -n $VIM ]; then
echo "----------------------------------------------------------------------------------"
fi
Update
It works when I run :sh, but not when I run commands from vim-fugitive. Is there is a way to intercept system() calls or whatever it is using?
From #tpope:
My recommendation would be to look into disabling the "alternate
screen" for your terminal emulator (or terminal multiplexor). That's
what I do.
Just add the following to tmux.conf
# tmux.conf
# For tmux , the alternate-screen option defaults to on
set-window-option -g alternate-screen off

Delete specific line from Zsh history

I'd like to remove a specific entry in my Zsh history.
Zsh's fc and history don't have any options to delete entries. I've tried looking for the ~/.zhistory but that doesn't exist. How can I go about finding the location of the history file and remove the entry?
You are looking in wrong File. Look at ~/.zsh_history not ~/.zhistory To view in which file your history is saved:
echo $HISTFILE
And delete:
rm $HISTFILE
Clearing Zsh History (oh-my-zsh)
close, quit and re-open iTerm
run nano .zsh_history
use the arrow keys to navigate to the part of your history you'd like to delete.
use the delete key to remove all unwanted history logs.
Once you've removed everything you'd like to remove, select control X to Exit.
You'll be prompted to Save the changes. If you're happy with your changes click shift Y.
You'll be asked where you'd like to save your changes. Select control T to save to File.
navigate to your .zsh_profile with your arrow keys and press enter.
Quit and restart iTerm.
type history to confirm the deletions.
You've successfully cleared your Zsh history.
osxterminalzshoh-my-zsh
Clear zsh history on unix systems.
echo "" > ~/.zsh_history & exec $SHELL -l
open ~/.zshrc
add the following line
alias clear_history='echo "" > ~/.zsh_history & exec $SHELL -l'
Save and close the file
Close the console or type zsh
if you to see the result directly, but this will open another zsh shell in the old one
Now you can clear the console typing clear_history
All the previous answers are good, this is simply the solution that worked for me.
You can use these commands to open the ZSH command's history(When you are in the home or ~ directory) and assume that you know how to use vim or nano :
nano ~/.zsh_history
vim ~/.zsh_history
open ~/.zsh_history
then you can delete the lines you want manually and save the file.
and if your zsh_history list is too long, for convenience use this:
enable mouse move and line numbering in the Vim environment by adding this to .vimrc:
open .vimrc:
vim ~/.vimrc
add these to .vimrc and save it(press ESC, enter ":" , write wq, and press enter):
:set number
set mouse=a
use the mouse to scroll easily in zsh_history by using Vim.
if you want to enable copy in Vim use holding shift on the keyboard.
read this for more info
https://www.techrepublic.com/article/how-to-effectively-clear-your-bash-history/
TL;DR
cat /dev/null > ~/.zsh_history
Type and run at the zsh command line, open ~/.zsh_history (This opens TextEdit on my Mac.)
Delete any lines in the file
Save and close the file
Close/Exit the Zsh completely and restart the Zsh (this step is important!)
Now, open zsh and the history command does not show the lines that you deleted
This function will remove any one line you want from your Zsh history, no questions asked:
# Accepts one history line number as argument.
# Alternatively, you can do `dc -1` to remove the last line.
dc () {
# Prevent the specified history line from being saved.
local HISTORY_IGNORE="${(b)$(fc -ln $1 $1)}"
# Write out history to file, excluding lines that match `$HISTORY_IGNORE`.
fc -W
# Dispose of the current history and read the new history from file.
fc -p $HISTFILE $HISTSIZE $SAVEHIST
# TA-DA!
print -r "Deleted '$HISTORY_IGNORE' from history."
}
If you additionally want to prevent all dc commands from being written to history, add the following in your ~/.zshrc file:
zshaddhistory() {
[[ $1 != 'dc '* ]]
}
Alternatively, for a comprehensive, out-of-the-box solution, use my Zsh Hist plugin.
E.g. with vim you can easily delete the last n lines like this:
Open file: vim ~/.zsh_history
Go to the bottom of the file: G
Mark lines: V -> move up with arrow key
Delete: d
Write & quit: :wq
Or you can just navigate with the cursor and delete any particular line with dd
Open .zsh_history with your favourite editor and save keystrokes.
e.g. subl .zsh_history will open up history in Sublime editor and then delete whatever you want.
You can use TextEdit or other editors also.
This worked for me:
LC_ALL=C sed -i '' '/line/d' $HISTFILE
Replace "line" with what you want deleted.
From this answer:
https://stackoverflow.com/posts/13661794/revisions
For ZSH
To locate the history file do :
echo $HISTFILE
Then simply edit the file and remove any lines you wish to be gone as you would with history -d id.
Save the file.
Open a new terminal and you should see that there is nothing to see anymore !
However I am amazed that history -d does not exists. If it does exists it's well hidden.

.bash_history does not update in Git for Windows (git bash)

I am using Git for Windows (ver. 1.7.8-preview20111206) and even though I have a .bash_history file in my HOME folder, it never automatically gets updated. When I start Git Bash, I can see in the history commands that I manually added to the .bash_history file, but it does not get updated automatically.
I used the shopt -s histappend command to make sure that the history gets saved every time I close the shell, but it does not work.
If I manually use the history -w command, then my file gets updated, but I would want to understand why the shopt command does not work as I understand it should.
Anyone can tell me why is this behavior happening?
I put this in my ~/.bash_profile
PROMPT_COMMAND='history -a'
Create the following files
~/.bash_profile
~/.bashrc
And put the following line in both of them
PROMPT_COMMAND='history -a'
To do this from the console (Git Bash) itself, use the following commands:
echo "PROMPT_COMMAND='history -a'" >> ~/.bash_profile
echo "PROMPT_COMMAND='history -a'" >> ~/.bashrc
What history -a means
From the history --help command
-a append history lines from this session to the history file
What is PROMPT_COMMAND?
Bash provides an environment variable called PROMPT_COMMAND. The contents of this variable are executed as a regular Bash command just before Bash displays a prompt.
Difference between .bash_profile and .bashrc
.bash_profile is executed for login shells, while .bashrc is executed for interactive non-login shells.
When you login (type username and password) via console, either sitting at the machine, or remotely via ssh: .bash_profile is executed to configure your shell before the initial command prompt.
But, if you’ve already logged into your machine and open a new terminal window (xterm) then .bashrc is executed before the window command prompt. .bashrc is also run when you start a new bash instance by typing /bin/bash in a terminal.
On OS X, Terminal by default runs a login shell every time, so this is a little different to most other systems, but you can configure that in the preferences.
References
https://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/x264.html
https://apple.stackexchange.com/questions/51036/what-is-the-difference-between-bash-profile-and-bashrc
As it was said here, to save git bash history on Windows you must not close the terminal with X button. Use exit command instead. History of commands will be saved then regardless of configuration mentioned in the accepted answer.
If you're using Git bash in VSCode please see C.M.'s comment above.
This worked for running git's bash in Visual Studio Code, but I had to put it ~/.bashrc not ~/.bash_profile. – C.M. Jul 29 at 14:43
This solved it for me.
There is a more complete answer on Unix Stackexchange, by Pablo R. and LinuxSecurityFreak. Add the following to your ~/.bashrc:
# Avoid duplicates
HISTCONTROL=ignoredups:erasedups
# When the shell exits, append to the history file instead of overwriting it
shopt -s histappend
# After each command, append to the history file and reread it
PROMPT_COMMAND="${PROMPT_COMMAND:+$PROMPT_COMMAND$'\n'}history -a; history -c; history -r"
Please be careful, though:
The problem with this PROMPT_COMMAND solution is that the numbers for each history item changes after each command. For example, if you type history(1) ls (2) rm, then you do !1 to repeat (1), the history number might change and might run the rm command. Chris Kimpton
If you use git bash for windows 8, just put this in your ~/.bash_logout file:
history > .bash_history
Obviously you need a ~/.bash_history file.
Regards.
For me what worked was going into C:\Users\MY_USER\ and deleting the .bash_profile file.
Ps: I am using windows 10
I am using Windows 10 for me it was a permission problem, my temporary solution was to add Everyone group and give it Full control on ~/.bash_history file.
By the way, for those using the Portable version of Git for Windows, there's no need to create .bash_profile or .bashrc. Simply add to C:<path to your Git Portable folder>\etc\bash.bashrc:
PROMPT_COMMAND='history -a'
Found an answer in another post : https://superuser.com/questions/555310/bash-save-history-without-exit
If you want to have an history updated between two terminals.
As a window user I created a file .bash_profile inside my user folder. And then I add the following content : PROMPT_COMMAND='history -a;history -c;history -r'
Just run this in your git bash
echo 'HISTFILE=$HOME/.bash_history' >> $HOME/.bashrc

Resources