Hacker News new | past | comments | ask | show | jobs | submit login
A Useful Thing in Bash (coderwall.com)
195 points by chaosmachine 12 days ago | hide | past | web | favorite | 54 comments

GNU Readline is really quite a remarkable piece of technology that everyone uses and yet hardly anyone has any idea how to actually use it efficiently.

Along the same lines of the article, these things have served me well:

This one is great for just getting the quick commands to help you get around the command line more efficiently


This one gives you all the exhaustive options around how you can tweak readline via your inputrc file


Its sounds really dumb, but after getting to know the bash and readline man pages I have stopped using fish and zsh and just started using more vanilla bash and built in linux tools and its been fantastic. I don't feel like I have lost any productivity and my terminal is a lot more responsive.

The long-form documentation is really useful:

https://tiswww.case.edu/php/chet/readline/rluserman.html - GNU Readline User Interface (info rluserman)

https://tiswww.case.edu/php/chet/readline/readline.html - The GNU Readline Library (info readline, long-form equivalent to the readline(3) man page)

Why these are hidden away on some random .edu web site rather than being under gnu.org... -\_:/_/-

(OK, to be fair it's on the official GNU Readline web page, but why _that_ isn't on gnu.org is the real source of my shrug!)

The Bash manual also includes a brief summary of readline usage (I guess they too didn't know where to find Readline's official documenation) and can be read at https://www.gnu.org/software/bash/manual/html_node/Readline-... or info '(bash)Readline'.

GNU Readline, for those who doesn't know, also comes with vi mode, where you can search with '/' and '?' keys. You can enable it with 'set -o vi' in bash shell or putting 'set editing-mode vi' it in ~/.inputrc.

If you put it in ~/.inputrc, you will get vi mode in all tools/shells which are using Readline like mysql, rlwrap, psql...


If using readline in vi-mode, I recommend also setting `set show-mode-in-prompt on` to provide visual feedback on which mode you're in. Maybe it's just me, but sometimes I walk away from a repl for quite a while (weeks sometimes) and when I come back to it I stumble for a moment because it wasn't in the mode I was expecting.

Agreed, I just wish it could be a bit more customisable. like so https://savannah.gnu.org/support/?109610

It's completely customizable! Just takes some creativity.


vi command line editing mode is required by POSIX (see under EXTENDED DESCRIPTION at https://pubs.opengroup.org/onlinepubs/9699919799.2018edition...)

Wow ! I have been using set -o vi for years but somehow completely missed that / and ? were available ! Thanks !

The line editing is good, as well as reverse search. I don't find myself using anything else sadly.

Forgive me for a semi-relevant question... How do you do tab completion in a "dd" command, e.g. "dd if=MyOs_version_<TAB>..." ? The equals always suppresses the completion.

bash-completion provides sufficiently smart completions for dd: https://github.com/scop/bash-completion/blob/master/completi...

Not quite a direct answer, but you could define a shell function for "dd" which took if and of as positional arguments and passed all the rest through.

Zsh with oh-my-zsh does the same. Pretty useful feature. It is good to know it’s that easy to configure it in bash.

But didn't zsh development get stalled?

Not at all (last commit to master 11 hours ago): https://sourceforge.net/p/zsh/code/ci/master/ (beware of the commit dates: they aren't necessarily in chronological order).

As opposed to what? And as if it needs new features?

Most recent stable release was 8 month ago.

oh-my-zsh had a commit 6 hours ago ;)

fzf is arguably more useful and replaces this and ctrl+r too

So much this. While tricks like the OP's do make history search just bearable, fzf just makes it how it should have been from the start :)

How did you plug it into history? Or do you just go $(history | fzf)? :)

fzf asks you if you want to enable this during installation.

On MacOS I installed it using Brew and I don't remember seeing any prompts :(

Edit: nevermind:

> # To install useful key bindings and fuzzy completion:

> $(brew --prefix)/opt/fzf/install

It’s quite funny and sad (no disrespect to OP or anybody) how people is still discovering what we people on fish take for granted. We can even auto-complete parameters only if we so wish. No need for any hidden setting, no need to install any additional (and usually heavy) packages. Built-in, baby.

I started using it when it was known as Ridiculous Fish, circa 2009-2010, and I've never looked back. I also learned ways of moving around the shell with Readline commands, but I cannot really attribute that to fish; I think I did that on bash/zsh as well.

I don’t have too many functions, so I cannot really say which one is really better as far as scripting goes, but with enough aliases and fish built-in functionalities, you’re pretty much set.

I've been using fish for several years now, but I always have to jump back to bash when I need to write an moderately complex command.

Does anyone know if there's an equivalent of Bash's `(...)` (without '$') in fish? What about anonymous pipes `<(...)` and `>(...)`?

The anonymous pipes are also called "process substitution", and are done with `psub` in fish:

    sjl at alephnull in ~/scratch/tmp
    ><((°> diff -U0 (ls -1 | psub) (ls -1 | grep -v foo | psub)
    --- /tmp/.psub.cIcXKeQj3O       2019-10-10 10:21:58.940444840 -0400
    +++ /tmp/.psub.7W6mBnxcQD       2019-10-10 10:21:58.952444799 -0400
    @@ -3 +2,0 @@

Amazing, this is exactly what I was looking for. Thanks!

zsh has many of these features also.

edit: not sure if it does out of the box actually, i use prezto

Exactly. I cannot answer for sure because it’s been years since last time I checked, but back then (and from comments here in previous thread, I’d say still) people was required to install extra packages to acquire such functionalities, and usually they would be a bit bloated.

This is inbuilt in fish-shell, which I highly recommend. (I understand the functionality is inbuilt in readline, what I mean is fish exposes it in this manner by default)

IMHO fish's history + autocompletion is even better because it keeps per-directory histories. You get the most likely match in the filesystem location you currently are while typing, and then can search for other matches on the fly with the arrow keys.

There's a plugin for zsh which implements the same behaviour (this is what I'm using now):


Zsh autosuggestions are not quite the same as the built in fish autocompletion. Fish's autocompletion has much nicer functionality.

Hmm, I've used fish for years before switching to zsh with this plugin, and I can't find any difference (although I might not have discovered every feature of fish). The 'front-end' behaviour of showing a greyed-out suggestion while typing with per-directory context, and flipping through options with arrow up/down behaves exactly the same.

I don't know about this. I use Ctrl+R a lot, and I sometimes like to be able to go up the history, then down to the command line I was writing. I probably need to try this (or a variant) out, thougt, as it boils down to muscle memory.

zsh: https://unix.stackexchange.com/questions/16101/zsh-search-hi...

YMMV, but I've used both quite a bit and I find the shortcut in the article much more convenient than Ctrl-R, at least if I'm actually sure of the first characters of the command. They're not exclusive, anyway. :)

This is great. Frankly ctrl-r is almost useless. I've never had it find the command I want, because if I can remember enough of the command to find it, I can just write the whole line myself. And if it was a black magic command I'll wind up digging through log files because I won't be able to remember enough of it to find it.

I usually just do `history | grep ...` instead; it's faster and more flexible than trying to flip through Ctrl+R matches.

That said, I did just install the history-search-backward and history-search-forward hooks in inputrc, and I can already tell I'll love these.

I do the same, except instead of `history` i grep the .bash_history file :-P

(i almost always need it for stuff i typed several sessions ago)

Just tag commands with a # at the end

> $ complex command here # tagHere

Later use the tag with ctrl+r

I do this all the time

Brilliant! Thanks!!!

See other post, there's a solution for most of your history search problems and it's called fzf.



check out https://github.com/dvorka/hstr which you can bind to CTRL+R.

tagging with # comment is also a nice trick

ctrl-r works great if you have a standard command with a long file path you can't remember.

Just an anecdote though.

It works best for me in the opposite situation: an easy-to-remember path or subcommand, as part of a long line (usually involving if or while, and a series of commands)

I constantly use ctrl-r to reuse my most recent cd/ssh/git commit message/etc.

in addition to settings mentioned in the article, I have these two settings as well:

    "\C-d": unix-filename-rubout
this allows me to delete complete filenames to the left of the cursor.. by default, you have Ctrl+w that deletes till whitespace and Esc+backspace that deletes words, but what I want most of the time is deleting filename

    set echo-control-characters off
this is occasionally useful for my workflow, when I use Ctrl+c to abort currently typed command, I do not like the control character mangling the command in case I wish to copy paste that command again

This is so much better than CTRL+R that I've bound the key combo (CTRL+R/F) to this. `history | grep` suffices in those rare cases where I need the original CTRL+R behaviour.

I tried binding the arrow keys first, but it turns out I sometimes give up in the middle of writing a command in favor of reusing one from recent history, for which I need the original arrow bindings.

It works like this in the Matlab console, of which I am a heavy user. I got used to it and always wondered why it wasn't the same in bash/ksh.

Thanks for the tip, but would it work also with ksh ?

Edit : ok just saw it is actually a readline functionality.

This was one of the only reasons I was using fish as that feature is by default.

First thing I do on every distro. Why is this not standard?

For a second I thought "isn't that already in bash!?" And then I realized what it does... Gosh, that's actually really useful (I wish I knew this earlier, now I need to do it in zsh).

I'm not 100% sure if it's in the default configuration or if it's something I turned on, but my zsh has the same 'search up/down based on the beginning of the line' style behavior.

Same here, probably something added by oh-my-zsh

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact