so that repeated commands are only stored once. Handy for those, like me, who reflexively type commands like "ps aux" when thinking about what to do next.
One history trick I use a lot that most people don't seem to know about is the !$ variable, which refers to the last argument of the previous command. It's basically a bash pronoun. !! is the entire previous command which is occasionally useful with find:
Alternatively, you can add ':p' to the third line. This will print out the command rather than executing it. Additionally, it's also added to your bash history, so you can add it by pressing the up arrow.
I have found "magic-space" more useful than ":p". This auto-expands history substitutions (like !$) when you press the space bar. You can bind it to the space key in tcsh or bash. It also works for !!, !vi, and other substitutions.
So, when you press ! $ <space>, it expands out to "foo" in place, so you can be sure that's what you wanted, and edit it in place.
I think :p predates magic-space. They're both decades old at this point though.
$_ is a variable for the same thing. The only difference winds up being the effect on the current line's result in your history: !$ is replaced while $_ stays $_ and so its meaning will change if you run the same command later, which can be what you want or not, depending.
Oh, I didn't mean "You should use $_ instead", just "$_ is also useful."
As I tried to indicate, you should ideally use whichever will make more sense in your history later. If the command you're typing should always be applied to that file, which happened to be the last argument of the previous command this time, then use !$; if the command you're typing should always be applied to the last argument of the previous command, and it just happened to be that file this time, use $_.
I've always found interactive history UI to be difficult to work with beyond the most trivial cases. Instead, I'd always find myself typing "history | grep ..." over and over again. Eventually I wrote an improved history command with built-in filtering: http://curtisb.posthaven.com/a-better-history-command
It's funny how personal workflows can be. I do the history|grep thing too, but never felt the need to automate it further. It's a relatively rare thing (maybe once a day), used when I know I did something specific in the past but forget a detail or two.
Instead, I generally drop little shell scripts around my work area for specific tasks. Working on iterating a build/install to chase a specific bug? Stuff it into a little script. Writing a find command to munge a bunch of files with xargs or -exec or whatnot and realize I'm into the third line or editting? Stop and echo it into a file, then finish it in emacs.
The idea of doing all that junk and then relying on the bash history file (instead of, y'know, the actual filesystem) to store it for me seems weird.
Ctrl-x e opens the current line in your $EDITOR, smoother than echoing, especially when there are pipes involved. Save it out as a script from there if you like.
It's C-x C-e in my bash, fwiw. And I tried getting used to this but it breaks locality by dropping the new file into /tmp instead of $PWD. Quoting a line isn't really that hard, or you can always cut and paste with the mouse.
I use screens and session variables to manage context, so scripts don't need to be "around my work area" but rather in the appropriate ~/.context/$SESSION/bin directory (or ~/bin if sufficiently general).
Again, personal taste leads me to say "yuck" to this one. You don't think that the appropriate spot to do an ad-hoc build integration is the source directory? You'd rather put it somewhere that has to do with the window into which you're typing (which for obvious reasons won't survive a reboot or copy) and not a place that corresponds to what you're actually doing?
Ah, if something's particularly specific to a directory subtree, rather than a particular context/task, I'll drop it in the tree sometimes, for sure. But my contexts very much correspond to what I'm actually doing (and my prompt includes the session), and so ~/.context/$SESSION/bin is "a place that corresponds to what [I'm] actually doing".
Which is not to take away from your "it comes down to personal preference" by any means - just trying to make mine a bit clearer.
I'm not sure just what you mean, but to try to answer: $SESSION contains a meaningful context name, not a nonce string. Stuff in ~/.contexts/$SESSION sticks around unless I manually remove it (I also store context specific history and config files there). If I need to access a script from another context, I can just give the full path - winds up working a little bit like namespaces.
Acme has an idea of guide files in each directory which store commands you commonly use in that directory. Acme maps a mouse button to "send this text to sh", so you can edit a command in the guide file, highlight it with a sweep of the mouse while holding down the left button, then release the left button and middle-click to run it in the context of the current directory. Over the years this mechanism has greatly improved my retention and usage of interesting and powerful shell commands, and decreased to near zero the amount of time it takes to construct the command and the number of errors I make while doing so.
Very much so; much like the GP, I would "history | grep" and even had it aliased to 'hg' (which is one of the reasons I don't like Mercurial, just to start another flame war), but then I was reminded of C-r, which I should have known better (as an Emacs user (that's two flamewars . . . )), but oddly hadn't been using as I was just too lazy to really learn bash in depth.
It's not the same as Ctrl+R - it actually doesn't look for a match in the middle of the string, only from the beginning of it, so while it's better with going back and forth between the matches, it matches less data to begin with.
To be fair, if your prompt is empty, up/down behavior doesn't change.
I guess I re-run commands fairly often, so for me the history-search-backward thing is very useful; when I just need to use the default up/down binding, I just hit Ctrl-E Ctrl-U (go to end of line, erase everything to beginning of line) and I'm good to go.
To expand on this, it searches based on what's on the left side of your cursor. So if your cursor is all the way on the left side, it acts as it did before. You lose nothing!
A funny story about "cd -". When I first started learning the command line during a programming course, they basically told us just enough to get by in order to complete the assignments. Somehow, "cd -" was mentioned but not "cd ..", so for a long time I used "cd -" as my only method for getting to the parent directory! (since that was usually where I had just come from). Reading about everyone discovering "cd -" much later in learning bash is very amusing, since I have been using it since day one (albeit in a totally incorrect way!)
I wouldn't be surprised to learn I'm the only living person still using doskey. Yes, in April 2013, and on W7. I autoload a file with macro definitions in cmd prompt window, and this works great for programs I want at my fingertips but don't want to clutter PATH with (or desktop with shortcuts, or create a .bat/.cmd etc; I do realise there are other ways to do that, but my solution works good enough since DOS times). The unfortunate thing with doskey aliases is you cannot use them as pipe recipient, they have to start at the line start. On the other hand, they can accept parameters.
That's why I use fish. Not only does it cycle like that by default, but it autocompletes entire commands, searches for the substring in the middle of words, looks better, is faster, etc etc.
It's unfortunately on the one hand too beholden to POSIX shell behavior, while still being too different from mainline Bourne derivatives. I've tried it a few times, and the cognitive load is too extreme for my 20+ yrs of POSIX brain-damage to work around.
I don't use fish for shell scripting, but I'm enjoying it as my primary environment after making these adjustments..
Status codes and argument lists:
$status # replaces $?
$argv # replaces $@
Aliases are just functions (configure your startup in
~/.config/fish/config.fish):
# alias ls="ls -lrth"
function lr; ls -lrth $argv; end
For-loops are familiar:
# for n in one two three; do echo $n; done
for n in one two three; echo $n; end
The lack of '!$' confounded my hard-wired fingers until I settled on Alt-u to avoid up-arrows (see /usr/share/fish/functions/fish_default_key_bindings.fish):
The remaining price for fish's pseudo-telepathic assistance is the occasional frustration with applications that rely on the value of a user's default shell (/etc/passwd).
I tried oh-my-zsh for that, but it was very slow to start up. I went back to fish when I realized that I had basically set up zsh to act exactly like fish.
I've been using Fish on my Mac for a while as well as some VPS' I have. At work I just installed it on our dev server.
It has a build in git status script you can include in your prompt that's awesome. Here's my fish prompt (note __fish_git_prompt):
function fish_prompt
set last_status $status
set_color $fish_color_cwd
printf '%s' (prompt_pwd)
set_color normal
printf '%s ' (__fish_git_prompt)
set_color normal
end
Since this is ugly clickbait, here is the "content" of the linked site:
> Create ~/.inputrc and fill it with this:
"\e[A": history-search-backward
"\e[B": history-search-forward
set show-all-if-ambiguous on
set completion-ignore-case on
> This allows you to search through your history using the up and down arrows … i.e. type "cd /" and press the up arrow and you'll search through everything in your history that starts with "cd /".
I don't know, when I read the title the first thing my mind jumped to was CTRL-r command searching. I was thrilled to see something similar but better.
I also love the history-search-{forward,backward} shortcuts. I took over the Raspberry Pi SD card image generation process back when we moved to Wheezy for the 'official' images and put this shortcut in to the default install with the hopes of leaving it there if no-one complained. Sadly someone did, I caved in, and it is no more.
Ctrl-R finds commands that contain the string anywhere. The method the OP posted finds commands that begin with the string. This is an important difference, and if you give it a try, you'll likely agree the latter is what you want most of the time.
Thanks for the clarification - although depending upon how you work, this is not much of a benefit. For instance - if you type "/path/to/script.sh" you want to search for the name of the script - not the beginning of the path.
This is a killer feature of emacs and M-x shell for me.
Now my command history is searchable, just like any other file or buffer I have open.
I use the same idea for any repl, R,python,ruby,node,clojure. Bash is just another repl.
The major advantage of the emacs buffer method is that a lot of tasks I do on the computer span many commands. I can search for one command I remember executing 3 months ago, and then review the series of steps I took before and after, along with the output.
Typically finding a single command I've executed before doesn't help a whole lot. I need context.
M-x shell is one of the first things I just show people when I introduce them to Emacs. I had a databases class a few years ago where the CLI program we used to interact with the database was a basically an input loop where you entered commands. It had absolutely no concept of history though so if you messed up a query you had to retype it or use the clunky copy and paste feature of whatever terminal emulator you were using. Emacs changed everything though be cause I could just kill my last command and paste it into the new prompt. I have since done this with many other commands and I love it.
I've recently been using shells inside Emacs exclusively and not even starting Terminal.app any more. I've got a couple of tips for anyone doing this, based on my (limited) experience:
1) Try eshell which allows you to use Emacs Lisp for shell scripting, as well as override some common programs to use Emacs instead (grep, man, etc). I'm someone who has never really bothered to learn shell scripting and am much more comfortable using Lisp, even Emacs Lisp which is sort of the crummiest of the popular Lisps (don't get me wrong I love Emacs) Obviously YMMV and if you know shell scripting this is a non-issue, but for me it comes down to being constantly surprised by the little bit of shell scripting I've had to do, and having Emacs Lisp work basically the way I expect (dynamic scoping, Lisp-2 and all)
2) Both eshell and M-x shell are not actually terminal emulators, so anything that requires a terminal emulator, like pagers, git log (ok this is a bad example since you should just be using magit, but anyway...) or some programs that update the terminal with their status act totally goofy and sometimes just break altogether. In this case, you want term-mode, which is a proper terminal emulator. Be sure to read up on the different modes as otherwise you'll get stuck inside that buffer ;) http://www.gnu.org/software/emacs/manual/html_node/emacs/Ter...
Hope this helps another Emacs novice... most of this I learned from here:
I use fasd: Its the best bash tool out there. Jump, search the previous history based on frequency of usage. It updates your search with its algorithm matching the most predicted one.
My bash does this automatically and I do not have a ~/.inputrc file. I'm on Mac OS X 10.8.2 using the Terminal app (which is a bash command line interface). I assumed this was a default feature of bash but apparently not. If somebody can explain to me why I have this feature by default, I would be grateful.
Bash will up/down between past commands, but it's unfiltered. This lets you type the first few characters you know you're looking for to find it faster.
With C-r you need to first type C-r, then type your search key. With the OP's inputrc nice hack, you first type the begining of your command, and then up. To me it is very different.
You sure? Not in the bash versions (3 & 4) I'm using... In anycase, I'll stick to C-R since I know it works universally. And I depend on C-R quite a bit.
C-r will search what you type afterwards, (e.g., "C-r ssh" will then show me the previous command that starts with "ssh") whereas this tip seems to be searching to match what you've already typed. Pretty cool, IMO.
1) If you work on multiple machines avoid heavy configuration and remapping of keys. It will frustrate you to no end. "Oh I forgot on this machine it is the up arrow on the other it is Ctrl+R" etc.
2) Up/Dn Arrows already do a useful thing -- they cycle commands in historical order. That is also useful in addition to the Ctrl+R history search.
I couldnt agree more.
I had a knee jerk reaction to say that it would be someone who works in bash who would say something like this, because constantly sshing in to various boxes and having to constantly tweak your various . files is a fucking pain.
But after thinking it over, I definitely know those who are awesome sysadmins, and require every bit of the setup to match their preferences before they will deign to work in that system.
You can still search chronologically by hitting up arrow without typing anything. Ctrl-R still works. The only thing that's frustrating for me is not having it on computers I haven't assimilated yet. ;)
Otherwise it works. But ... ctrl U to clear the line, doesn't clear it completely. It only clears text from the start of the line to the prompt. What has been added from the history is left there one the line. I have to first move to the end of the line then type ctrl U to clear it.
reply