I feel like discussion of 'sensible bash defaults' is incomplete without mention of .inputrc. My most "can't live without it" setting for bash is actually an .inputrc setting:
# From http://www.ukuug.org/events/linux2003/papers/bash_tips/
# Incremental searching with Up and Down is configured in .inputrc
"\e[A": history-search-backward
"\e[B": history-search-forward
... so if I type `ssh <up arrow>` I get the last command that started with `ssh`, not the last command I ran. oh-my-zsh thankfully does this by default as well. But I still use my .inputrc on server boxen where I don't want/need to install a different default shell.
Also worth noting that all of those `bind` commands in OP's script are actually .inputrc lines if you remove the `bind` and surrounding quotes.
This is why these things are so personal. I'd hate this. The up/down bindings are absolutely tied to specific command orders in my head. I need to know that "three commands back" is wherever I was in the sequence of commands that I'm repeating.
If I'm trying to semantically query my history (for "ssh") in this case I'll use the ^R binding to incrementally search the history, or literally grep ~/.history for what I'm looking for.
That's not to say that you're "wrong", just that calling these things "sensible defaults" is sort of missing the point. Nothing about them is sensible for everyone.
If you just press "up" without typing anything first then it works as you expect. I find ^R annoying if I've already started typing the command and then realise I can search the history (although that's probably configurable).
Once you get used to it, the only downside of up/down history search is when you ever use a shell that doesn't do it and you feel lost.
On a standard Ubuntu install: If you press ^R after already typing part of what you're searching for, and then press a key (space, or more of the command you're searching for), then it'll switch to the history-search mode with that value pre-filled in.
if you want to search for a string match anywhere in the command rather than at the beginning. It might be 'substr' rather than 'substring' depending on your Bash version.
Obviously the utility of this depends on your keyboard layout and config, as much as it does on personal preferences.
Yup, it changes the default behavior slightly but as @omalsa04 mentioned if you just hit <up> without typing anything it will iterate through the whole command history, the same as it would without this binding.
So that is where it actually comes from. I was wondering for some time now. This is one of my favorite features on oh-my-zsh!
It mostly helps when you type complicated command and after half an hour you need to repeat it for some reason. You type the command you used, and hit a arrow up.
Prepending cd for directory names would be kind of bad for me.
I tend to create local scripts to initialize project environments using their root directory name. So the automatic prepending would make the action ambiguous as a command.
That's the first thing I disable every time I set up oh-my-zsh on a new box. I think it should not be a default behaviour and should only be enabled if needed.
May be an old-fart prejudice, but my eyes cross to think that 'dash and underline are equivalent' might be a desired thing. Making bash be clever seems like a pile of pitfalls.
If you have an inconsistent naming convention in your directory structure, this could speed things up/save some memorization.
I'm not a fan of adding features that make poor choices less painful, but I could see using it for a little while as I'm getting to know a non-ideal environment.
I don't have any file or folder name starting with a dash, while underscores are pretty common. Treating dashes and underscores as equivalents saves you one keystroke (i.e. you can type `cd -folder<tab>` instead of `cd _folder<tab>`).
Oh no, I totally understand - typing this on a happy hacker keyboard ;).
I'm just somewhat of a cynic, since my workflow tends to fall on its face when I'm on a server that uses special snowflake rc files. Furthering that cynicism.. these days I'm just using plain /bin/sh for any shell scripts just because of the amazing level of bloat that exists within bash.
You mean it saves you one edit in the case where you've mistyped the directory name? Otherwise it seems like no keystrokes are saved among the two you show.
EDIT: groan, ok, you win. Net -1 keystroke for most keyboards.
Hey guys! If you are interested in "different" shells and REPLs I suggest you check out Ammonite-REPL / Ammonite-Shell -http://www.lihaoyi.com/Ammonite/ It's written in Scala and well. It looks ql. :)
This looks pretty sane overall. If you try this, be aware that it changes directory navigation, i.e. "Prepend cd to directory names automatically, so you can cd into directories just by typing their name", "Automatically correct spelling errors in arguments supplied to cd". I've tried these things and they drove me insane, so they're not good defaults for everyone.
I like it. It is not a complete revamp of bash to something else (the zsh-comment below is not fitting), it just enables some comfort features bash readily supports. One can argue about the case-insensitivity, but I see no other option that could be controversial. Just a small collection of sane defaults.
Sane defaults, useful aliases, no dependencies and easy to expand upon. I made it mostly to give either a sensible default rc file to extend, or just a general high quality prompt.
I'm a big fan of zsh. It doesn't seem to be solely focused on just "doing what you mean", which some of these tweaks seem aimed at; it seems aimed more at correctness. e.g., it would allow you to pass * .txt into a command if * .txt doesn't match anything. Bash will just assume I mean literally '* .txt' so you get different behaviour depending on whether or not there's a wildcard match. zsh has taught me the good habit of always using \* when I don't explicitly want shell expansion.
edit: spaces add after asterisks to avoid formatting weirdness
Heh, fish shell contributors had a long discussion of failed wildcard expansions at https://github.com/fish-shell/fish-shell/issues/2394 . We all pretty much agreed that bash's passglob behavior is really bad.
zsh's default is much better. Though to be fair, bash-style passglob behavior can be enabled in zsh by setting NO_NOMATCH. zsh is still zsh, after all.
There's still plenty more wildcard nuttiness. A favorite is to execute a bare *: zsh will try to execute the first file, passing the other files as arguments!
will only match files, not directories, symlinks etc.
ls **/*.jpg(.L-3000000on[1,5]) **/*.png(N)
will match .jpg files in the current and all subdirectories, which are:
. files
L-3000000 with "length" (size) under 3MB
on ordering them numerically
[1,5] and only the first five
plus any .png files, if they exist (N = it won't fail if they don't).
I have some scripts with expressions this complicated, but day-to-day it's useful for finding empty files (L0) or excluding directories. "man zshexpn" and search "Glob Qualifiers".
2) Glob operators:
ls DSC<100-200>.JPG
matches files with names between DSC100.JPG to DSC200.JPG.
setopt extended_glob
ls *.java~*Test*
matches all .java files, except those matching Test*. Same man page, search "Glob Operators".
3) Lazy for-loops (single command doesn't require do-done), and taking two variables:
echo "A 1" > tempfile
for i j in $(<tempfile); echo $i $j
Interactively, shell history seems to be nicer, I use a couple of global aliases (alias -g L='| less'), and the completion system completes everything you can possibly think of, like usernames, hostnames, remote filenames, HTTP URLs, processes (for kill)...
There are http://www.commandlinefu.com and the like. I copy and paste stuff from the web into the shell occasionally, I'm sure everyone does. I do use fish, but it is annoying sometimes, it's missing the most basic stuff like backticks. So much so that I think I'm going to stop.
This is a non-issue. The `!#/bin/bash` at the top of scripts will tell the interpreter which shell to run. And any one liner I've found online for bash has also worked on zsh (for me), but even if it didn't: `bash -c ls`
Today I learned people actually write / use scripts without specifying the interpreter at the top of the script. This is like writing a Ruby script and expecting it to work when calling it with the Python interpreter.
These history settings should clearly be the real defaults. I wonder how difficult it would be to get them changed upstream?
Upstreaming would also allow improvements, for example PROMPT_COMMAND='history -a' doesn't update history until the next prompt is displayed. If you close your terminal while a program is running then the last command entered is not saved.
Some great ideas here--a lot of them solve problems I've personally had with bash over the past 15 years--but plenty of these feel like solutions in search of problems.
I'm tempted to post my own commentary but I'd probably make the same mistakes. What would be really fantastic is a usability study of bash to see what the common pain points are.
Does anyone know if bashscript could be updated to allow spaces between assignment? I can't see how it would break existing programs (but I'm sure there's a catch) and scripts would be much cleaner (and less of an headache).
A breaking example might be trying to find lines containing an "=" in a file:
grep = my_file
Also a problem is the syntax for running a program with environment assignments that apply only to the program:
env1=foo env2=bar env3= my_program
Note that under POSIX rules, "env3" here is assigned a zero-length string. Making these sorts of assignments work with spaces around the equal signs would open up a can of worms.
HISTFILESIZE is kind of a misnomer. It's the maximum number of lines in HISTFILE, where HISTSIZE is the maximum number of commands. If you have HISTTIMEFORMAT set, then each command gets at least 2 lines, plus the possibility of multi-line commands.
That's true, but everytime I say the words z shell, someone always says "Fish!", so I figured I'd pre-empt them for once. Go figure it would backfire on me. LOL.
Also worth noting that all of those `bind` commands in OP's script are actually .inputrc lines if you remove the `bind` and surrounding quotes.