“I have [bash] history back to ~2003”
twitter.com
twitter.com
$ history | wc -l
56201
I use a simple prompt_command hook to push my history (from all my machines) to a central MySQL database(https://github.com/fredsmith/history-db). Entries are de-duped and a tally is kept so I can do simple ad-hoc reporting: mysql> select * from history order by count DESC limit 10;
+-------+---------------------+-----------+----------+-------+
| id | timestamp | command | hostname | count |
+-------+---------------------+-----------+----------+-------+
| 1 | 2015-09-02 19:41:45 | ls | xicada | 34458 |
| 89 | 2015-09-02 14:58:33 | cd .. | xicada | 4332 |
| 519 | 2015-08-24 18:38:55 | ll | xicada | 3229 |
| 9 | 2015-09-02 12:37:05 | cd | xicada | 2250 |
| 82 | 2015-08-28 18:27:07 | add | xicada | 1887 |
| 329 | 2015-08-31 18:22:49 | gs | xicada | 1817 |
| 48 | 2015-09-02 19:17:26 | git pull | xicada | 1696 |
| 275 | 2015-08-24 18:23:44 | df -h | xicada | 1529 |
| 15708 | 2013-10-08 01:33:33 | grid unn1 | Europa | 1210 |
| 44 | 2015-08-31 13:10:46 | git push | xicada | 1139 |
+-------+---------------------+-----------+----------+-------+
10 rows in set (0.02 sec)
It's pretty useful (I search through my history constantly with ctrl-R or using bash's history-search-backward hotkeys), and having a 56K line history file doesn't seem to impact history searching or shell startup any noticeable amount.I'll see what I can do for a hosted/SaaS system this weekend.
Oh, relevant XKCD. https://xkcd.com/1068/
Usually this takes years!
$ which ls
/usr/local/opt/coreutils/libexec/gnubin/ls
I'd say $392 seems like less than I should contribute.Which makes me wonder, does Apple have an official stance on supporting open source they use?
That's good, because it would be extremely disturbing if someone from the FSF/GNU coreutils team thought charging like this was okay.
"We've scaled enough. It's time to monetize." -Richard Stallman, Founder. FSF.
Maybe true, but keep in mind that the main coreutils maintainers (including the parent) are funded by Red Hat. There are plenty of FOSS projects that do suffer from a lack of funding; coreutils, GCC, etc are certainly not one of them. As such, if your goal is to help the FOSS community at large, you might want to consider channeling the money to other important projects.
Maybe the donation link already does such channeling; I am curious about this.
This project is entirely satirical. Read through to the bottom of the README.
$ history |wc -l
82230
This is just from my work machine (~4 years old), my history is not centralized but after seeing all this I think I'm going to work it into my centralized dotfiles system.Also, I can confirm that gigantic bash histories don't affect the speed of anything.
Super useful/essential tweaks -
export HISTCONTROL=erasedups
export HISTSIZE="NOTHING"
export HISTFILESIZE="NOTHING"`
shopt -s histappend
export PROMPT_COMMAND='history -a;echo'
erasedups will erase any earlier instance of an indentical command, keeping your history file lean. Setting HISTSIZE and HISTFILESIZE to something nonnumeric makes for no limits. histappend appends to the HISTFILE when the shell session exits. And my prompt command appends each executed command to HISTFILE immediately after it's executed. With histappend, this may be redundant. (The prompt command also gives me a blank line after each command finishes.)That mysql setup is pretty cool too, it's a rich man's
$ history | awk '{print $2}' | sort | uniq -c | sort -rn | head -10
14365 vi
11006 sudo
6976 ls
6898 svn
5322 cd
3869 cdb
2809 svnvimdiff
1846 ggrep
1474 git
1285 ssh #!/bin/bash
cd /Users/nmjohn/.directory_history \
&& git add . \
&& git commit -m "Automatic Backup: `date`" \
&& echo "Files Modified:" \
&& git log head -1 --name-only --pretty=format:"" | grep "[^\s]" | awk '{print "\t\t"$0}' \
&& echo ""
It's not bullet-proof, but since I never manually touch the directory it's worked without hiccup for the last ~6 months. When trying to remember the syntax to a rarely used function (or even the name itself) or coming up with a gnarly awk/sed/grep command, it's been incredibly helpful to have fairly granular search capability to go back and find them weeks later.Also ctrl+g in a terminal toggles between per directory history and global history which makes context switching easier when switching to a project not touched for a while.
On the topic of the article I have per directory history going back to ~2013 when I wrote the script.
Having said that I didn't use it too much yet, I have my regular history in place too.
I've been pretty happy with my bash history solution, but thinking about the return value, one big thing I think would be handy would be to have a default filter for searches that removes commands that returned an error code. They might be handy to see every once in a while, but for the most part, I wouldn't want to re-run one of them.
I use bash-preexec [1] to hook on the even just before executing a command. I'm kind of nervous if my string quoting is safe though.
I guess you'd have to set the history-size etc large enough to hopefully last for the maximum expected shell run-time.
EDIT: hmm, the man page says you can just unset HISTFILESIZE or set it to a non-numeric/negative value to avoid truncating the history file at all.
export HISTSIZE=65535 # why not?
export HISTFILESIZE=65535
export HISTCONTROL=ignoredups
but now I'm wondering if I should unset `HISTFILESIZE` insteead.If you're planning on keeping a lot of history, ignorespace makes it easy to avoid inserting commands with sensitive info. A well-placed $(cat) can work too.
$ PASSWORD=hunter2 # sensitive info doesn't go into history
$ curl -O http://name:$PASSWORD@server/path # command with correct syntax does go into history cat `find "${HOME}/.history" -type f | grep -v ".allhistory"` > ${HOME}/.history/.allhistory
history -r ${HOME}/.history/.allhistoryOthers have mentioned several handy tweaks for doing this, but I didn't see all of the ones I use so I thought I'd share them here. One of the important bits is the HISTIGNORE. I am interested in commands that I might want to search for and run again one day, so I filter out commands I consider to be clutter.
# Configure my history preferences
# Load history substitute into readline rather than immediately executing
shopt -s histverify histreedit
set histappend
# don't put duplicate lines or lines with leading spaces in the history. See bash(1) for more options
export HISTCONTROL=ignoreboth
export HISTIGNORE='&:bg:fg:cd*:clear:ls:pwd:history:exit:make*:* --help:'
export HISTTIMEFORMAT="%m/%d/%y - %H:%M:%S "[fzf] is ctrl-r on steroids.
[fzf]: https://github.com/junegunn/fzf
It's a fuzzy pattern matcher for your shell history (and lots more).
I started using Homemaker recently https://github.com/FooSoft/homemaker which is a very clean/lightweight replacement for GNU Stow, Homesick, and other dotfile managers. The Go versions of these utilities are always simple and single-purpose.
Modern developers are returning to building Unix style systems programs. Time is being spent on that instead of the usual bulky python scripts that have been popular recently or the million personal-productivity web apps people were creating.
ctrl-r (find something) enter (execute) ctrl-r (find something I have to change) home/end (change, then enter)
with fzf ctrl-r and selecting always gives me just a string where I then have to press enter, it just behaves like dmenu for the console basically if you look at the bash bindings, which unfortunately is a bit less flexible unless I am missing some option that would allow this
alias ..='cd ..'I also have "la" as an alias for "ls -a", and "lsa" as an alias for "ls -lah --color=auto"
There is just this impedance mismatch between our brains hazy recollection of things and the exactness that is required by computers. I find that fuzzy search combined with stats like most-commonly-used bridge this quite well!
I also don't run a keylogger.
Also means you don't have to retype complicated commands too often.
Practical example: I remember I cleaned up some calibre converted epubs with perl a couple months ago, because they had a piece of text injected by some kind of generator on every page. It took me some time to figure out the exact replacement patterns, and if I were to do it again, I just need to do:
$ history 0 | grep perl ... 823 perl -0777 -i.original -pe 's#<b class="calibre1">Generated by ABC Amber LIT Conv<a href="http://www.processtext.com/abclit.html" class="calibre2">erter, http://www.processtext.com/abclit.html</a></b></p>\n<p class="calibre3">##g' part1.xhtml 825 perl -0777 -i.original -pe 's#<b class="calibre1">Generated by ABC Amber LIT Conv<a href="http://www.processtext.com/abclit.html" class="calibre2">erter, http://www.processtext.com/abclit.html</a></b></p>\n<p class="calibre3">##g' *.xhtml ...
Then inspect the history around those commands to find exactly how I got to that point.
find . -type d -print0 | sort -z | xargs --null -I '{}' du -sh '{}' | sort -h
Simple and clear; but history gives you the convenience to do find<C-R><CR> and having the command run with out parameter/typo verification.
You can filter things like ls and ps.
I assume you have the in-memory history enabled, but still
So I end-up with never-closing task-based window sessions and occasionally copy-paste commands to a safe file for future reference.
I really should investigate the root cause some day...
shopt -s histappend
In your .bashrc should do. To have it write after every command take a look at http://unix.stackexchange.com/a/1292(In zsh I believe it's:
setopt inc_append_history
setopt share_history
) shopt -s histappend
export PROMPT_COMMAND="history -a;$PROMPT_COMMAND"
in your ~/.bashrc.Also, if you want fresh history in an already opened window (assuming you added the above), do "history -n". E.g. if you typed "longcommand" in window1, then switch to window2, do "history -n" and uparrow, and "longcommand" will be there.
A much better system would be to have a user daemon centralize history (among other things). The benefits would be numerous:
- Better performance
- (optional) Sync between concurrent shells
- No history overwriting problems / race conditions
In addition, this daemon could be used to enable other programs such as autojump. These programs work with the current system, but are based on a hack and as such have needlessly poor performance.
As much as I like my command line, I think it would be very worthwile to rethink this whole system from scratch.
$ cat ~/var/history/bash.d/* | wc -l
464291
$ for year in 201{2..5} ; do
echo -n "${year}: "
cat ~/var/history/bash.d/${year}* | wc -l
done
2012: 116285
2013: 175525
2014: 117928
2015: 54553
It's not a complete history, as I filter several commands with HISTIGNORE. echo "Password: "; read -s pass; stuff --pass "$pass"
Where stuff takes password as an argument. Alternatively you can start your line with a space character and it isn't stored in your history.For zsh, you need to have HIST_IGNORE_SPACE set.
ls <M-p>
inserts the most recent command in history that begins with 'ls ' in the command prompt. I don't know why this isn't the default, as it's extremely handy. Also it works with any CLI program that uses readline.
If you want to try it out, add this to your ~/.inputrc file.
"\ep": history-search-backward
"\en": history-search-forward
https://github.com/uxcn/scripts/blob/master/misc/bash/newsbe...
· --merge immediately incorporates history changes from other sessions.
Ordinarily fish ignores history changes from sessions started after
the current one. This command applies those changes immediately.It's like ctrl-r, but it shows you many candidates at once.
If avoiding them is really important, I don't think you have any choice other than to go the whole hog and basically implement half of Maildir.
Mostly because I can't switch to another machine within 1s
1. Start an interactive shell. 2. Enter a command you want saved. 3. Exit this shell. 4. Start another shell. 5. Be unlucky such that the new shell has the same PID as the previous one.
This is not something to worry about.
And due to the way Bash is developed, all you need is the same Bash executable you had in 2003 to ensure all the commands actually work.
Instead of simply scrolling through your recent bash history when you press <UP> (which still works the same when your prompt is empty), it filters out any command that don't match the partial command you've already typed. For example, typing "cp " and then pressing up will find the last "cp" command that I typed.