13 ms·
Advancing in the Bash Shell
- ilaksh 10y agoBash has lots of cool features, but zsh has more and better defaults, and fish is even better.
- rajangdavis 10y agoThis is tight. Thanks for sharing, the history portion at the beginning is really cool.
- giosch 10y agoI thought that i knew more than i actually know. Thanks!
- yarapavan 10y agoRelated: BASH FAQ - http://mywiki.wooledge.org/BashFAQ http://mywiki.wooledge.org/BashFAQ Also, look at the screen tips by the same author - http://samrowe.com/wordpress/2010/06/16/gnu-screen-quick-tips/ http://samrowe.com/wordpress/2010/06/16/gnu-screen-quick-tip...
- pmoriarty 10y agoI virtually never use !! any more. Instead I just type control-r followed by a portion of the command in my history that I'm interested in. That's a much more interactive way of getting to the command I want, and if the first match isn't what I want I can either keep typing more of the command or type control-r for the next match. I can also type control-s to go to the previous match. For that last trick to work, you need to do something like this first: stty stop "" Granted, I use zsh, but I think it works pretty much the same in bash. Another trick I really like, which I've only used in zsh, but which might exist in bash too (since bash and zsh have so much feature parity these days) is to bind a keystroke to "insert-last-word". When this keystroke is hit, it appends the last argument of the previous command to the end of the current line, further typing of this same keystroke will remove the appended argument and instead append the last argument of the previous command, and so on. I use this all the time and therefore never have to type !$ And my favorite shell trick of all time: set -o vi
- igg 10y agofzf [0] works pretty well for this. [0] https://github.com/junegunn/fzf https://github.com/junegunn/fzf
- pmoriarty 10y agoIs there any way to force the installer to compile from source rather than downloading a binary? I'm a little wary of precompiled binaries.
- icebraining 10y agoThere's a Makefile in the src directory, seems like you can run "make release" to compile from source.
- pjmlp 10y agoDo you also validate the whole source code, including running it through static analysis, before compiling it?
- marklgr 10y ago> When this keystroke is hit, it appends the last argument of the previous command to the end of the current line There's `Meta-_` to insert the previous last word, but you cannot cycle with the previous words--it inserts the last word of the previous commands. You can give it a count, though (with Meta+nums).
- Myrmornis 10y agoAgreed, but even nicer than control-r are the readline functions `history-search-backward` and `history-search-forward`. Personally I bind them to up/down which on OS X at least involves: # Put this in some file like ~/.readline-bindings "\e[A": history-search-backward "\e[B": history-search-forward # And this in your ~/.bashrc or ~/.zshrc bind -f ~/.readline-bindings That way if you haven't typed any input it behaves like normal up (previous command), but if you've typed some characters it only retrieves matching commands. http://codeinthehole.com/writing/the-most-important-command-line-tip-incremental-history-searching-with-inputrc/ http://codeinthehole.com/writing/the-most-important-command-...
- adamnemecek 10y ago> Some people hold the belief that using a GUI is faster than using a CLI. I've heard more people say this than that GUI is faster. Also it really depends on what you are doing.
- kbenson 10y agoI think Coding Horror gave a fairly succinct overview, including sources[1]. As usual, it's incomplete understanding and cargo-culting of opinions until the statement in question bears little resemblance to the original assertion. 1: https://blog.codinghorror.com/revisiting-keyboard-vs-the-mouse-pt-1/ https://blog.codinghorror.com/revisiting-keyboard-vs-the-mou...
- pjmlp 10y agoI rather use a REPL environment that combines GUI and CLI, like in Xerox and ETHZ OSes. Think of DrRaket, Swift Playgrounds or Jupyter like experience.
- contextfree 10y agoYes, there's far too little of this. I'd love something that combines the good points of Powershell and a GUI file explorer for example. Even the primitive out-gridview or ogv is incredibly handy.
- pjmlp 10y agoPowershell is probably the closest we have currently in terms of that experience.
- fphilipe 10y agoI used to do !$ a lot until I configured iTerm to allow me to cycle through the last args with alt-. which is way faster. But I did not know about the colon modifiers, so !$ might make its way back into my workflow. ZSH gives me a nice overview of what's possible: > !$:<tab> & -- repeat substitution A -- absolute path resolving symbolic links Q -- strip quotes a -- absolute path c -- PATH search for command e -- leave only extension g -- globally apply s or & h -- head - strip trailing path element l -- lower case all words q -- quote to escape further substitutions r -- root - strip suffix s -- substitute string t -- tail - strip directories u -- upper case all words
- ashayh 10y agoDo you use Ctrl+R a lot? You should give fzf a try: https://github.com/junegunn/fzf https://github.com/junegunn/fzf It works for both Vim & Bash.
- kbenson 10y agoI don't use !!, or !$, because I prefer to see what command is being executed before I press enter. For the same reason, I will never use !word. But that's not a problem, because as others have noted bash makes it easy to not have to fall back to these. Alt-. will generally add the prior last argument into the current command, and repeated presses will cycle through previous commands. Ctrl-r will dynamically update to show you the prior command matched as you start typing afterwards, so you can confirm it's correct. Both are essential if you want to reuse prior commands but either can't trust that you were the last person using the shell, or don't want a typo to ruin your day, and possibly many other people's day as well. That is, if you're a sysadmin using the automatic variants, I don't want you anywhere near systems I rely on, I want you far away. Perhaps working for a competitor.
- angus-g 10y agoI've got 'bind Space:magic-space' in my .bashrc, which performs history expansion after you hit space, maybe that partially helps. I guess there's friction if the expanded command isn't the one you want, which the interactive methods are better at dealing with.
- mturmon 10y agoI use this bash feature also. I think this not just "partially helps", I think it completely addresses the problem described by the above commenter. Perhaps s/he is not aware of this feature.
- executesorder66 10y ago> I don't use !! Not even "sudo !!" ? You can see the command you just typed in the line above, and you just forgot to add sudo to it.
- kbenson 10y agoNope. It's easier to not have to make a decision about when to use !! or not, so I just don't. Up, Ctrl-a, "sudo ", Enter. Another way of putting it is that I'll gladly press another 2-3 keys if it prevents a class or errors and also reduces the number of special bash instructions I have to keep in memory. !! isn't even in my repertoire, but I don't feel its loss.
- foota 10y agoI didn't realize that you could do something like: vim <(find . | grep coolfile) until just the other week, pretty dang useful.
- bgaluszka 10y agoI often use `git grep something | vim -` which puts list of files into vim with line numbers, and then I do `gF` to get to file and particular line.
- foota 10y agoI didn't realize vim supported reading from standard in, thanks!
- dllthomas 10y agoYou can go one further. I have an alias 'cbuf=vim - -ccbuf!' This takes whatever is piped in and loads it into the quickfix list. So I get locations out of anything with lines of the format "file:line: something" or "file:line:col: something". Eg: git grep -n | cbuf
- svckr 10y agoOne of my favorite discoveries as well! I sometimes (rarely) compare archives with: diff <(tar tzf f1.tgz) <(tar tzf f2.tgz) Or diffs of diffs: diff <(git diff --cached) the-patch-alice-proposed
- JoshTriplett 10y agoOne more handy one, when you have a complex command to deal with: C-x C-e will open up the current command line in your text editor, and when you save and quit, it'll run the line. So if you want to do some complex editing operation on the command line, you can do so with your preferred editor.
- Mojah 10y agoSo happy to see this article get traction, it truly deserved it! Many unknown Bash tricks! I featured it in the cron.weekly newsletter 2 weeks ago: https://www.cronweekly.com/issue-44/ https://www.cronweekly.com/issue-44/
- noobermin 10y agoI wonder how many people know a few of these (like ctrl-a and ctrl-e and other navigation commands) come not from bash per se but from readline[0]. It isn't a surprise, then, that these mirror emacs commands. For example, one I use often is ctrl-k to kill to the end of a line...and, yes, just like emacs, you can yank it back with ctrl-y too :)...I often do this if I type out a huge command, forget that I needed to type another before, so I use that to "save" commands before execution. That is, it's essentially cheap copy and paste on the commandline. Cherry on top? These work on other readline using tools! They work in the interactive repl's like python, node, irb, ghcim the exact same shortcuts... it makes working with repl's much more pleasant for me. [0] https://cnswww.cns.cwru.edu/php/chet/readline/rltop.html https://cnswww.cns.cwru.edu/php/chet/readline/rltop.html [1] quick note, node might use a readline like but it doesn't support yanking (pasting) unfortunately.
- js8 10y agoAnother very useful feature related to brace expansion are sequences: {1..99} will give 1 2 3 4 5 .. 9 10 11 12 .. 98 99 {01..99} will give 01 02 03 04 05 .. 09 10 11 12 .. 98 99 And so on. I think it also works with letters.
- 0xmohit 10y agoBrace expansion can also be nested: $ echo {a..c}{1..5} a1 a2 a3 a4 a5 b1 b2 b3 b4 b5 c1 c2 c3 c4 c5 It is worthwhile noting that brace expansion is strictly textual and is performed before any other expansion.
- FoeNyx 10y ago> I think it also works with letters. Indeed it does. According to the man page : "When characters are supplied, the expression expands to each character lexicographically between x and y, inclusive, using the default C locale." $ echo {a..z} a b c d e f g h i j k l m n o p q r s t u v w x y z But it does not seem to work with ranges outside ASCII such as "à..é", "あ..お", or smileys range, even though my locale should be ".UTF-8" compliant. Also, you can specify an increment value : $ echo {0..42..7} 0 7 14 21 28 35 42 $ echo {z..a..3} z w t q n k h e b
- coldpie 10y ago> Indeed it does. According to the man page : "When characters are supplied, the expression expands to each character lexicographically between x and y, inclusive, using the default C locale." I think 'x' and 'y' are probably the worst variable names they could have chosen for this sentence :)
- mturmon 10y agoThanks. And as your last example illustrates, downward ranges are automatically invoked: $ echo {10..1} 10 9 8 7 6 5 4 3 2 1 As are negative endpoints (shown below with some automatic number formatting, which is turned on when either the first or the second endpoint is padded): $ echo {2..-002} 0002 0001 0000 -001 -002 I just noticed that all this is documented behavior -- another illustration of how rococo this shell has become.
- david90 10y ago[Danger, do not try to run in your system] I like this :(){ :|: & };: which is a fork bomb http://askubuntu.com/questions/159491/why-did-the-command-make-my-system-lag-so-badly-i-had-to-reboot http://askubuntu.com/questions/159491/why-did-the-command-ma...
- 0xmohit 10y agoAnother good read: Bash Shortcuts For Maximum Productivity [0] [0] http://www.skorks.com/2009/09/bash-shortcuts-for-maximum-productivity/ http://www.skorks.com/2009/09/bash-shortcuts-for-maximum-pro...
- deleted 10y ago[deleted]
- lolive 10y agoI like this article a lot. A lot of funny tricks to try and learn. A missing piece of information IMHO: Ubuntu now maps a nice readline features to PgUp and PgDn: history-search-backward and history-search-forward. Type the beginning of a command line, and with PgUp-PgDn, you will traverse your history for the command lines beginning with what you have typed. That's a no-brainer in my Bash life. Note: to enable that feature in your Bash, here is a tutorial: http://dqxtech.net/blog/2011-03-06/linux-bash-history-pgup-pgdown http://dqxtech.net/blog/2011-03-06/linux-bash-history-pgup-p...
- hibbelig 10y agoI know of "M-." which will insert the last word of the previous command, and typing "M-." again will replace it with the last word of the command before that. Is there something that goes through the words, instead? So I hit a key, it inserts the last word of the previous command, then I hit the key again and it replaces it with the penultimate word of the previous command? I think using bang, I can do "!-3:1" to get the second word of the command three lines up?
- partycoder 10y agoI use fish. It's not a popular choice of a shell, but the autosuggestions feature saves a LOT of time.
- ilaksh 10y agoI use fish also. Its more popular than people admit because it makes things easier.
- jkot 10y agoMy best progress in shell was by switching to Fish. Much more intuitive for programmer. Guess what this does: while true clear df sleep 1 end
- dllthomas 10y agoI second the voices, one downvoted but none really addressed, wondering why this is manifestly an improvement over the bash equivalent. I certainly don't demand that everything in Fish be an improvement over everything in bash for Fish to nonetheless be superior... but this was presented specifically as an example of how Fish is great, and I could just as well say "Guess what this does" of the obvious bash equivalent: while true; do clear df sleep 1 end
- deleted 10y ago[deleted]
- INTPenis 10y agowhile sleep 1; do clear df done
- snvzz 10y agowatch -n1 df
- appelza1 10y agowhile true; do clear df sleep 1; done --Bash equivalent, not sure I see your point
- deleted 10y ago[deleted]
- INTPenis 10y agoHistory manipulation in bash only reminds me why I have both the current commands history number and the last return code in my prompt. I don't need colors, or anything fancy in my prompt, but those two things I find to be really useful. export PS1='[\u@\h \W](\!/$?)$ '
- aoloe 10y agoI almost never use any of the "shortcuts" explained. And I wonder if it would be worth learning them. They look much more cumbersome than the alternatives, I use in my everyday work. I have to admit, that -- at some time in the past -- I've even tried to activate vim mode. As a heavy vim user i thought it would make sense. At the end I'm stuck with the Emacs-inspired (is it really Emacs?) shortcuts. They seem to be the ones that make most sense in the short living, very interactive, shell command line: - Arrows for going up/down one or two commands, - ctrl-r for interactive searching in the history, - ctrl-a for going back to the beginning of the row, - ctrl-e to the end, - del & and backscape for deleting a bunch of chars, - in some case ctrl-w for deleting words backwards (mostly for deleting the url in the latest wget command), - and, of course, tab completion. When I'm in need for more complex interactions: - I start vim and - work with a mix of !! commands (shell that outputs the result in the current vim buffer), - vim manipulations (vertical selections, ctrl-x-f, qq short living macros), A and I with a . repeat), - join everything in a row and yank it and, finally, - a :!ctrl-r" to run it. When the interaction is even more complex, than it's time for a shell script. Last resort being a Python script. Now, why would I take the time to write `rm my-file{-01,-02,old}` and risk getting a typo into it, instead of relying on the tab-autocomplete?
- lolive 10y agoYou definitely should read the comments about "history-search-backward" and "history-search-forward". There are a real nice addition to your list.
- aoloe 10y agoyes, that looks like a useful command... does not work here on a mac, but i can think of using it! thanks for mentioning.
- lolive 10y agothe usual configuration of a .inputrc is given for a PC keyboard. the safest method for you is to edit your ~/.inputrc with vi(m). go to insert mode, type " type Ctrl-v type PgUp (->a strange string is displayed), type the following string ": history-search-backward Do the same on another line for PgDn (replace backward with forward). Save. Relaunch a Bash session. And that's it.
- Zardoz84 10y ago^a I would remember it
- gitaarik 10y agoDid you know Ctrl + / is like undo while composing a command? So when you for example delete a word with Ctrl + W, you can get it back with Ctrl + /.
- gravypod 10y agoI wouldn't ever day that the GUI is the fastest way to interact with a computer. It's just the safest and simplest. Those are usually more important then speed.
- _ZeD_ 10y ago"Some people hold the belief that using a GUI is faster than using a CLI." wha?
- dorfsmay 10y agoI consider this misinformation and makes my blood boil. I feel like the author learn partial information and decided to write a blog about without researching further... ctrl-R is not bash, it's GNU readline. http://cnswww.cns.cwru.edu/php/chet/readline/rluserman.html http://cnswww.cns.cwru.edu/php/chet/readline/rluserman.html If you are going to use command line, than absolutely you should use command history editing, but why limiting yourself to a few commands learned through osmosis or haphazardly rather than use a full editor? Why use C-r to search backwards, but not M-backspace to delete an entire word? When I explain this, people usually argue that "there are two many weird commands to learn, and I only need the few I know". The same type of people often go on a rant about how much vim is so much better than emacs. There are not weird command to learn, none, zero! Use your preferred editor! You already know it, you already know all those commands, and if you don't buy a book and learn them! You know and like emacs? Great, that's the default in readline. Go ahead C-r, C-backspace, C-a, C-e, M-f all you need. You already know all of those. But you don't like emacs, or don't even know that it exists beside the fact that it's something fun to shit on? You think you're a big shot because you know vim really well? Not an issue, type the magic command "set -o vi" and you are now in vi mode, you can esc-/ to search, esc-k to call the last command, and once editing a command, cw to change word, $ to go to the end of the line, etc... I do not buy "I'm a vim person, but I just use ctrl-R and the arrows", because you are basically limiting yourself just because you had not realised readline is a full editor. You have nothing to learn, just set the editor mode in your preferred editor mode, and start using it, trust me, you will start getting use to it and use its power very quickly. BONUS: It' snot just bash! Any program that use readline can do the same! psql etc... use it (or a something like readline, because of GPL vs non-gpl etc...). BONUS 2: You can use readline with software that don't use it, it's call rlwrap. Go ahead, use "rlwrap sqlplus" once, then try to use oracle without it!
- deleted 10y ago[deleted]
- dllthomas 10y ago> ctrl-R is not bash, it's GNU readline As readline was codeveloped with bash, I think it's incorrect to say it's not bash. It is bash by way of readline - additional information important for some contexts, not for others. > cw to change word, $ to go to the end of the line, etc... But not, sadly, ci" to change what's inside quotes. ---- As to your obviously troubling experiences with some vim users, I apologize on behalf of my sect. But tone down your characterizations - there are plenty of smug and superior emacs users as well. (For my part, I don't much care what others use as long as they actually learn their way around some sort of powerful editor.)
- rbonvall 10y agoA trick I used to use in the floppy disk era: $ mount /mnt/floppy $ mv !$/file_I_needed . $ u!mo The last command would umount(8) the floppy. I use !! all the time, specially when first using find to see which files I will operate on and then doing the actual operation: $ find . -name '*Foo*.scala' path/src/main/scala/foo/Foo.scala path/src/test/scala/foo/FooSpec.scala $ git add "$(!!)" Shameless plug: I actually use nq, my find wrapper: https://github.com/rbonvall/nq https://github.com/rbonvall/nq
- selfsimilar 10y agoOne note I wish the author would add is that ^a to move to the beginning of a line often conflicts with screen or tmux as a command prefix, so I tend to use ^x^x as a replacement.
- aabajian 10y agoGiven the title of the article, I was really hoping that the author would answer the following question. Suppose I have the following line: >rsync ~/20160604/apache-tomcat-7.0.63/webapps/ROOT/contact.html apache-tomcat-1:/svr/apache-tomcat-7.0.63/webapps/ROOT/ I'm rsyncing the contact.html file to my website. Now I want to rsync the index.html page. I do this by: 1. Pressing the up arrow key to get the previous command. 2. Press and hold the back arrow key until it gets to "contact.html" 3. Press and hold backspace to delete "contact.html" and type "index.html" My question is: How to quickly move the cursor to a location on the line. For example, in Vi I could do "F+c" twice to move to the first "c" if this were a text file. I know I can enabled Vi commands for Bash, but this seems cumbersome. There has to be a way in Bash to jump around the already typed line.
- Gorgor 10y agoIt's not as precise as vi movement, but for most command line activities I find the Emacs-like movements sufficiently practical: M-b: back one word M-f: forward one word C-a: beginning of line C-e: end of line I also don't like to use the arrow keys because they are so far away, so: C-b: back one character C-f: forward one character C-p: previous command C-n: next command And since I'm making a list now anyway: C-k: Kill to end of line. C-u: Kill to beginning of line. C-y: Yank (put/paste) last killed string. You can then cycle further through the kill ring with M-y. But I have a question concerning Emacs movement: M-b and M-f are rather similar to vim's b and e, respectively, meaning they don't jump to the beginning/end of the non-whitespace-string. That's why vim has B and E. Is there anything similar in Emacs?
- mikelward 10y agoThe equivalent in Emacs mode (the bash default) is Ctrl+]. Alt+<number> followed by that goes to that <number> occurrence of the character, so "Alt+4 Ctrl+] c" would go to the 4th c. Ctrl+Alt+] searches backwards in the same way. But I find just about anything better. !!:s/contact/index/ ^contact^index alias r='fc -e - --' # if not already present r contact=index or if you know ahead of time, do them both together rsync ~/20160604/apache-tomcat-7.0.63/webapps/ROOT/{contact,index}.html
- falcolas 10y ago
- falcolas 10y agoOne that I love that is missing: M-# (i.e. alt-shift-3) Comments the line currently being edited and places it at the top of history. Great when searching back through history and editing a line safely before executing it.
- ramses0 10y agoMy favorite tip in this vein is "fc" => Fix Command, along with "#my_command --here". If you're unsure of a command, press insert a leading "#" to make it a comment (Up-Arrow, Ctrl-A, #, Enter). Then "fc" will load that command into $EDITOR where you can have full text edit capabilities before writing and exiting the file to execute the command. I know there's some magic keystrokes to get into vi-mode from the command line but I can never remember them, whereas "fc" is pretty easy to remember for the rare occasion when I need it.
- dllthomas 10y agoThe magic keystrokes are whatever fires the "edit-and-execute-command" command. If you're in emacs mode, it's C-x C-e. Mnemonic: e for editor, x because it's emacs and lots of stuff starts with C-x If you're in vi mode, it's v from normal mode, so if you're in insert mode it's escape, then v. Mnemonic: v for vi
- noisy_boy 10y agoTip for "set -o vi" users: when you have issued a long multiline command and your line wrapping isn't working very well, Esc-k until you get to the command and then press v - this will open your command in vi and you can now edit it more easily. Quitting with :wq will execute your command.
- dllthomas 10y agoStrictly it will open your command in $EDITOR, but if you've "set -o vi" that's probably vi/vim/neovim. Outside vi mode, C-x C-e does the same thing. It's "edit-and-execute-command" in readline. Incidentally, this really does what it says on the tin: if you use "read -e" to enable readline support at a prompt, and you try to edit what you're inputting this way, it won't pass the result into the read - it will try to execute it.
- gavinpc 10y agoRegarding alias ssh=’ssh -AX’ alias ls=’ls –color=auto’ Let me quote the Mercurial manual: > It is possible to create aliases with the same names as existing commands, which will then override the original definitions. This is almost always a bad idea![0] I was recently bitten by this when running a build on a new machine. I was doing a log -r "$revision" and instead of getting one commit message (as usual), I was getting the entire log history up to $revision. I managed to find that Mercurial had made a breaking change[1] so that `log -fr` would now have the observed behavior. But I was only running `log -r`! But on the old machine, I had in my .hgrc the alias log=log -f To top it off, I also had a comment with the above quote that this is "almost always a bad idea!" Consider me burned! [0] https://www.selenic.com/mercurial/hgrc.5.html#alias https://www.selenic.com/mercurial/hgrc.5.html#alias [1] https://www.mercurial-scm.org/wiki/UpgradeNotes#A3.4:_minor_changes https://www.mercurial-scm.org/wiki/UpgradeNotes#A3.4:_minor_...
- 1amzave 10y agoAlso (more specifically to one of the given examples), enabling `-A` on all your ssh invocations likewise seems like a pretty bad idea.