11 ms·
Shell Tricks That Make Life Easier (and Save Your Sanity)
- zahlman 7mo agoNot a fan of the LLM-flavoured headings, and the tips seem like a real mixed bag (and it'd be nice to give credit specifically to the readline library where appropriate as opposed to the shell), but there are definitely a few things in here I'll have to play around with. One thing I dislike about brace expansions is that they don't play nicely with tab completion. I'd rather have easy ways to e.g. duplicate the last token (including escaped/quoted spaces), and delete a filename suffix. And, while I'm on that topic, expand variables and `~` immediately (instead of after pressing enter).
- ta8903 7mo agoSpeaking of readline, I recently found out PowerShell has a readline mode (https://learn.microsoft.com/en-us/powershell/module/psreadline/about/about_psreadline https://learn.microsoft.com/en-us/powershell/module/psreadli...) and it works great. As someone who works mostly in WSL and has to use PS occasionally, it really reduces the overhead of the context switch.
- School-Cotton 7mo agoReadline is close enough to being part of bash that it’s not really inaccurate to call these all shell features imo.
- integralid 7mo agoExcept not everyone uses bash shell - so it's not really accurate.
- croemer 7mo agoNot just the heading is LLM-flavoured. So is the writing, e.g. "The shell is a toolbox, not an obstacle course."
- zahlman 7mo agoYeah, there are a few of those, but overall there wasn't really enough prose in total to really irritate me. And those LLM-isms do come from somewhere, and I really do get the sense that some humans are effectively training themselves off of AI now.
- aa-jv 7mo agoMy favourite shell trick is to comment my code: $ some_long_command -with -args -easily -forgotten # thatspecialthing ... Some weeks later .. $ CTRL-R<specialthing> .. finds: $ some_long_command -with -args -easily -forgotten # thatspecialthing Need to see all the special things you've done this week/whenever? $ history | grep "\#" ... Makes for a definite return of sanity ..
- senectus1 7mo agoomg >$ CTRL-R<specialthing> I could kiss you.. this alone is amazing!
- aa-jv 7mo agoYes indeed, it is very fun to discover this if you don't know it already, it expands your understanding of your shell life immensely, doesn't it?
- fragmede 7mo agohttp://atuin.sh http://atuin.sh adds a database to store history in and a custom app to use for lookup with added modes to help with searching.
- 000ooo000 7mo ago!?specialthing? If you are feeling brave
- skydhash 7mo agoI don’t keep history. Any commands I think will be useful, I save it in a script.
- scbrg 7mo agoI once saw this pattern referred to as a bashtag, which I think was an excellent name (no matter if you actually run bash as your shell or not).
- aaravchen 7mo agoOne of the peer comments alludes to this and mentions that it's bash only. Doesn't work in zsh by default apparently.
- tetris11 7mo agoNever heard of instant truncate, nor `fc`, nor `Esc .` Quite a few useful ones
- chasil 7mo agoA much larger base for ksh (as a pdksh descendent) is Android. OpenBSD is a tiny community in comparison, although Android has acquired code directly from OpenBSD, notably the C library. The vi editing mode is always present in ksh, but is optional in dash. If present, the POSIX standard requires that "set -o vi" enable this mode, although other methods to enable it are not prohibited (such as inputrc for bash/readline), and as such is a "universal trick." The article is relying on some Emacs mode, which is not POSIX. $_ is not POSIX if I remember correctly. History in vi mode is easier, just escape, then forward slash (or question mark) and the search term (regex?), then either "n" or "N" to search the direction or its reverse. I've seen a lot of people who don't like vi mode, but its presence is the most deeply standardized.
- fellerts 7mo agoCTRL + W usually deletes everything until the previous whitespace, so it would delete the whole '/var/log/nginx/' string in OP's example. Alt + backspace usually deletes until it encounters a non-alphanumeric character. Be careful working CTRL + W into muscle memory though, I've lost count of how many browser tabs I've closed by accident...
- gryfft 7mo agoCtrl-Shift-T usually brings that tab right back at least
- hejira 7mo agoIn my terminal it's the exact opposite – Alt-Backspace deletes to the previous space, whereas Ctrl-W deletes to the last non-alphanumeric (such as /). I'm using fish shell in an Alacritty terminal. Yeah, pressing Ctrl-W accidentially is a pain sometimes ... but Ctrl-Shift-T in Firefox is a godsend.
- Aerolfos 7mo ago> Yeah, pressing Ctrl-W accidentially is a pain sometimes ... but Ctrl-Shift-T in Firefox is a godsend. Fun fact: despite having absolutely no menu entry for it, and I believe not even a command available with Ctrl+Shift+P, Vscode supports Ctrl+Shift+T to re-open a closed tab. Discovered out of pure muscle memory.
- fainpul 7mo ago
- Joker_vD 7mo ago> The “Works (Almost) Everywhere” Club > The Backspace Replacements Also known as "emacs editing mode". Funnily enough, what POSIX mandates is the support for "vi editing mode" which, to my knowledge, almost nobody ever uses. But it's there in most shells, and you can enable it with "set -o vi" in e.g. bash.
- ZeroGravitas 7mo agoVi mode is also available in Claude code and gemini-cli to give some recent examples, and a bunch of other places you might not expect it, as well the more obvious places where code is written. Once you get used to it, it is painful to go back.
- mr_mitm 7mo agoMy biggest complaint about the fish shell is the lack of true vi mode. They attempt to emulate it and it works to some degree, but it's no comparison to readline's implementation.
- maleldil 7mo agoYou can always use Alt-E to open the command line in $EDITOR if you need more powerful commands. I find it better to use readline for small changes and jumping to vim for bigger ones.
- School-Cotton 7mo agoHave you tried a recent version? An issue I opened about this years ago was finally closed, they claim it’s fixed now. I haven’t tried the purported fix, though.
- mr_mitm 7mo agoYes. It has improved, but it's still not there, and probably never will be. See my reply to your sibling comment.
- 7mo ago
- voidUpdate 7mo agoWith ctrl+r, if you press it twice, it will autofill the search with whatever you last searched for. pressing it more will go back through the history. Been using that a lot recently when doing docker stuff. ctrl+r, type the container name, keep going until I get the compose build command. ctrl+r, ctrl+r, repeat until the log command. Then I can just mash ctrl+r to get the build and log commands. Ctrl+r is your friend. ctrl+r
- arcanemachiner 7mo agoMake sure to add fzf + shell integration for maximum Ctrl+r goodness.
- ZeroGravitas 7mo agoAlso worth reading the intro to fzf search syntax. https://junegunn.github.io/fzf/search-syntax https://junegunn.github.io/fzf/search-syntax. The $ and bang and exact search are neat, but the bit at the bottom as to why `gadd` or `gas` is a better search for `git add something` than something with full words and spaces is a revelation when first using fzf.
- tkocmathla 7mo agoI love this, from a comment on the article: He had in his path a script called `\#` that he used to comment out pipe elements like `mycmd1 | \# mycmd2 | mycmd3`. This was how the script was written: ``` #!/bin/sh cat ```
- internet_points 7mo agoYes! That one's going in my $PATH. Such a useful use of cat!
- rgrau 7mo agoA similar trick: #!/bin/sh $* that's my `~/bin/noglob` file, so when I call a zsh script from bash that uses `noglob`, it doesn't blow up.
- 000ooo000 7mo agoWhat does it provide over mycmd1 #| mycmd2
- chriswarbo 7mo agoTheirs "turns off" one element of a pipeline; yours turns off everything after a certain point. This will output the stdout of mycmd1: mycmd1 #| mycmd2 | mycmd3 This will output the stdout of mycmd3: mycmd1 | \# mycmd2 | mycmd3
- mkoryak 7mo agoCan you explain to me why either of these is useful? I've somehow gotten by never really needing to pipe any commands in the terminal, probably because I mostly do frontend dev and use the term for starting the server and running prodaccess
- agons 7mo agoI can imagine a pipeline where intermediate stages have been inserted to have some side effect, like debug logging all data passing through.
- talkin 7mo ago> cd -: The classic channel-flipper. Perfect for toggling back and forth. And not only cd. Gotta love 'git checkout -'
- piekvorst 7mo agoThe '-' shortcut is weird. In 'git commit -F -', the '-' is actually /dev/stdin.
- deleted 7mo ago[deleted]
- account42 7mo ago- is a pretty standard idiom for using stdin/stdout instead of a named file that you can find in many commands. I don't think it conflicts with the cd/checkout usage though as there the argument normally does not refer to a file so having - mean stdin/stdout doesn't make sense.
- mpyne 7mo ago`-` is the traditional shell way to refer to stdin/stdout (as with your git commit example) but also the traditional way to refer to the last directory you were in (as with git checkout/switch). You would never pipe the output of a command to `cd` so the `-` shortcut couldn't be helpful to cd as-is. So rather than invent yet another shortcut to memorize for `cd` they reused the existing one which otherwise would be redundant, which I appreciate at least. But git is simply being consistent with the shell to further reduce the cognitive complexity of reusing shell commands you're used to in analogous git contexts.
- faangguyindia 7mo agoI just open, agent in tui, and ask it to do what I want and make a plan, i read the plan edit it and run it. Simple, no need to learn any commandline these days. I used to use arch and all, and managed many big projects. I find little value in learning new tools anymore, just feed it docs and it generated working plan most of the time Now I've moved to coding in Haskell, which i find suits me better than wasting my time with cli and exploring what options all these cli tools have.
- worksonmine 7mo agoWhat is it like to be this proud of not learning the tools you use? Do you really think several paragraphs to an agent that may or may not be correct is the "easy" way compared to just checking the manual for the flag you want? I will never understand people like you.
- faangguyindia 7mo agoTools are means to end. They don't matter much to me.
- bigstrat2003 7mo agoThat's fine to a point. But if you don't learn your tools, you will have rendered yourself unable to catch when the LLM gets things wrong (and it will get things wrong because it doesn't understand anything it touches). That, in turn, will mean that you're going to struggle to reach your desired ends but won't have the understanding to figure out what's wrong. "Tools are just a means to an end" means you need to not get attached to a tool if it's not doing the job. It doesn't mean you don't need to understand your tools.
- chriswarbo 7mo agoI'm confused; how is writing a shell command (using shortcuts like those in the article!) "wasting time", but describing what you want to an LLM, having it make a plan, reading the plan, editing it, and running it is somehow not a waste of time? You also mention there being "little value", when your proposed approach costs literal money in form of API/token usage (when using hosted models). > Now I've moved to coding in Haskell You might like https://hackage.haskell.org/package/turtle https://hackage.haskell.org/package/turtle or http://nellardo.com/lang/haskell/hash/ http://nellardo.com/lang/haskell/hash/
- ahmedfromtunis 7mo agoUsing the terminal becomes much more cozy and comfortable after I activate vim-mode. A mistake 3 words earlier? No problem: <esc>3bcw and I'm good to go. Want to delete the whole thing? Even easier: <esc>cc I can even use <esc>v to open the command inside a fully-fledged (neo)vim instance for more complex rework. If you use (neo)vim already, this is the best way to go as there are no new shortcuts to learn and memorize.
- rzmmm 7mo agoOh wow I didn't know about this, thank you. The underlying feature is called "readline vi-mode" for folks who want to search more about it.
- commandersaki 7mo agoI've been a (n)vim user for 20+ years now, but I hate vi-mode in the shell. However if I feel that I need to do a complex command, I just do ctrl-x+e to open up in neovim (with EDITOR=nvim set). I find it a good middle ground.
- sudonem 7mo agoAgree. I WANT to love it - and if I was only ever working on one, or a small number of systems that I was the only one working on I’d probably do it. I’m ALL about customizing my environment. However ssh into various servers through the day (some of which are totally ephemeral), and having to code switch my brain back and forth between vim mode and emacs mode in the shell would just slow me down and be infuriating each time I connect to a new box.
- xtiansimon 7mo agoHuh. I don’t use vi-mode for more than jumping to the beginning or end of a line, which I like a lot.
- irishcoffee 7mo agoYou mean, like the “home” and “end” buttons?
- ta8903 7mo agoSomething that should be mentioned is starting a command with a space doesn't add it to your history in most shells, really useful for one-off commands that you don't want cluttering your history. Also, increase your `$HISTSIZE` to more than you think you would need, there have been cases where it helped me find some obscure command I ran like 3 years before.
- vdm 7mo agoCtrl-r works well at searching character trigrams, which can include space. Trigrams without space work well with auto_resume=substring . `| sudo tee file` when current user does not have permission to >file
- deleted 7mo ago[deleted]
- amelius 7mo agoWhat confuses me is that Ctrl+Y "yank" means the opposite of what it means in Vim. Certainly does not help with keeping my sanity.
- antiframe 7mo agoIt all depends on your perspective. Are you yanking into your kill ring or yanking out of your kill ring? I had trouble with yanking and killing until I realized the complement to yanking, killing, only makes sense in the into-the-kill-ring" direction, so yanking must be out of the kill ring. When I use vim, which I don't think has a kill ring but registers, I think I am yanking into a register and then pasting from a register later. So, just ask yourself this: "are you using a kill ring or register to store your text?" and the answer becomes clear.
- alex_smart 7mo agoThat is because the terminology (and the keybindings) come from the Emacs tradition, not vim. Most shells come with “vim mode” as well, but at least in my experience, the dual mode editing paradigm of does not feel like a good fit for the shell.
- hikarudo 7mo agoOne trick I use all the time: You're typing a long command, then before running it you remember you have to do some stuff first. Instead of Ctrl-C to cancel it, you push it to history in a disabled form. Prepend the line with # to comment it, run the commented line so it gets added to history, do whatever it is you remembered, then up arrow to retrieve the first command. $ long_command <Home, #> $ #long_command <Enter> $ stuff_1 $ stuff_2 <Up arrow a few times> $ #long_command <home, del> $ long_command
- fragmede 7mo agoFwiw, in Bash, alt-shift-3 will prepend the current command with # and start a new command.
- j4cobgarby 7mo agoMore generally, it's alt-#. On an ISO (e.g. UK) keyboard layout, shift-3 isn't a hash.
- dotancohen 7mo agoThank you so much! I do this constantly. For me it was Ctrl-A Shift-3 Enter - two keystrokes too many.
- gvalkov 7mo agoIn zsh you can bind "push-line-or-edit". In bash and all readline programs, you can approximate it with C-u followed by C-y (i.e. cut and paste). My history is still full of '#' and ':' (csh trauma) prefixed command-lines like you described though ...
- idoubtit 7mo agoYou missed an easier alternative that was in the article: ctrl-u saves and clears the current line, then you can input new commands, then use ctrl-y to yank the saved command. With zsh, I prefer to use alt-q which does this automatically (store the current line, display a new prompt, then, after the new command is sent, restore the stored line). It can also stack the paused commands, e.g.: $ cp foo/bar dest/ <alt-q> $ wcurl -o foo/bar "$URL" <alt-q> $ mkdir foo <enter> <enter> <enter>
- quijoteuniv 7mo agoGuilty as charged
- nasretdinov 7mo agoI'd advise against using sudo !! though since it adds the command to history and then it's very easy to accidentally trigger, running some undesired command as root without any prior confirmation. IMO pressing up, Ctrl-A and typing "sudo " isn't much longer but saves you from running unknown commands as root by accident
- 000ooo000 7mo agoI have a bash key binding, Ctrl+Y, that prepends sudo to the current command and submits it. I also don't use sudo-rs. No one has died yet.
- kgwxd 7mo agoDecades ago, i used a small dns host. I wanted to switch a personal site and they just couldn't get the final step of the transfer to work. A ton of "try now" emails spanning several weeks. Then one day, I was trying to setup MySQL on a personal Linux machine, and it wouldn't let me use my "standard password" for the admin account. I knew I could just use a different one, but I really wanted to know what the problem was. Took a long time, and I don't remember how I figured it out, but I eventually tracked it to the password ending with '!!'. It took a while to put it together, and I never confirmed with the dns host support it's what fixed the issue but, I changed my password there, tried the transfer again, and it worked without any help from support. I suspect my plaintext password played some part in a script used in the transfer process, and was outputting the previous command in place of the !! I wish I had asked them if that was it, but if it was, they would have to admit to having my plain text password, or lie about it.
- cocoto 7mo agoPrepend your command with a space and now your command is not saved in the history.
- sltkr 7mo agoThat depends on the shell configuration. On bash, you can achieve this by setting HISTCONTROL=ignorespace but that's not the default.
- commandersaki 7mo agoMy favourite trick is either commenting out a whole command or placing a comment at the end of a command to make it easier to find in my persistent history (thanks eliben) [0], using the # character. I tried this in zsh and it wasn't the default behaviour which immediately made me nope from the shell altogether, among all the other quirks. I've just been using bash for far too long to switch to something different. [0] https://eli.thegreenplace.net/2013/06/11/keeping-persistent-history-in-bash https://eli.thegreenplace.net/2013/06/11/keeping-persistent-...
- amelius 7mo agoWhat I hate is that if you start a command with a space it is not recorded in the history. This happens often when copy+pasting commands. I know you can turn it off but still ... this drives me mad.
- prodigycorp 7mo agoThere's one thing you need to only think about once, and has the potential to save you a ton of time: profile your ZSH startup time! Stuff like NVM or Oh My ZSH will add a few seconds to your shell startup time.
- sva_ 7mo agoI can recommend powerlevel10k with instant prompt enabled. https://github.com/romkatv/powerlevel10k https://github.com/romkatv/powerlevel10k
- chrisweekly 7mo agogood call if you care about perf, fnm is better/faster/cleaner than nvm. (also, mise is able to manage "all the things", not just node) IME omzsh slowness usu relates to overloading it w plugins, which I've never found a need for...
- wewtyflakes 7mo agoAgreed. I lazy-load NVM to get around that: lazy_nvm() { unset -f nvm node npm npx [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" } nvm() { lazy_nvm; nvm "$@"; } node() { lazy_nvm; node "$@"; } npm() { lazy_nvm; npm "$@"; } npx() { lazy_nvm; npx "$@"; }
- exceptione 7mo agoI didn't know the `ALT + .` trick to repeat the last argument, but what is even more neat (and not mentioned in the article) is that it cycles through your history. At least it does in my shell.
- keybored 7mo ago> We’ve all been there. Close tab. I ought to migrate away from shell scripting and just keep the shell for interactive use. Unfortunately I have cursed myself by getting competent-ish with P. shell and Bash scripting. Meaning I end up creating maintenance headaches for my future self. (Echoes of future self: ... so I asked an LLM to migrate my shell scripts to Rust and) Anyway with the interactive shell stuff. Yeah the I guess Readline features are great. And beyond that I can use the shortcut to open the current line in an editor and get that last mile of interactivity when I want it. I don’t really think I need more than that? I tried Vim mode in Bash but there didn’t seem to be a mode indicator anywhere. So dropped that. Edit: I just tested in my Starship.rs terminal: `set -o vi`. Then I got mode indicators. Just with a little lag.
- joombaga 7mo agoYou can use `set vi-ins-mode-string` and `set vi-cmd-mode-string` in .inputrc to get indicators in readline, and you can add them to your prompt with a bit more work: https://superuser.com/questions/1466222/move-vi-mode-string-to-end-of-bash-prompt https://superuser.com/questions/1466222/move-vi-mode-string-...
- aaravchen 7mo agoI struggle with this all the time. It's easy to start with some shell commands, and nothing beats the direct terminal running nature of a shell script. But at some point you get to where you need to do things shell isn't good at, and the cost of maintaining that part can put weight the ease of direct terminal access. Especially if you then throw in the need to make your solution runnable on a lot of systems, you now have a problem with compatibility and possibly environment setup. On top of that, if you're really experienced and good with shell, the bar for "this is difficult" in shell gets further and further away, even if it's hard for someone else to maintain. I've been investigating alternative options with bring-your-own-tool for this situation at $JOB, mostly making use of shebangs to trigger environment setup from self-contained utilities packaged with the scripts, and there are some promising options. Things like `uv` to setup a self-contained one-off python venv automatically so you can write in Python instead, possibly with one of the packages that helps with the many subcommands footguns, or to write `xonsh` if you want something more shell script leaning but with Python power. Or you can alternatively go with a language agnostic solution and use shebang triggered `nix-portable` to construct a whole isolated custom environment automatically from a flake.nix and run whatever tools and mishmash of languages you want.
- piekvorst 7mo agoIs it just me, or is it an LLM language? The article tries very hard to be correct but somehow lacks experience. I've never used the majority of these tricks for decades, except for brace expansion, process substitutions, and complex redirections.
- xeyownt 7mo agoI knew many of these tricks, but learned many new tricks I didn't know and looks very useful (like you can do Ctrl-Y after an Ctrl-U, the 'reset' or 'disown' thing). Regarding experience, I'm also struck by how many "experienced" engineers are just clueless with the keyboard.
- codeinred 7mo agoI think the keybinding suggestions are really nice. My shell is configured by default such that Alt+Left and Alt+Right move by a word, but having things that work out of the box, basically always, is really useful whenever I need to do things inside a docker container
- fzeindl 7mo agoMy header on top of every script #!/usr/bin/env bash set -eEuo pipefail # shellcheck disable=SC2034 DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" #######################################################
- TacticalCoder 7mo agoWait... Most of my shell scripts have zero unused variables: I prefer to comment them if I may need them later on. Why do you disable SC2034? I don't think not having unused variables prevent me from doing things in my scripts!? I understand if it's a preference but SC2034 is basically one of my biggest timesavers: in my case unused variables are typically a bug. Except, maybe, ANSI coloring variables at the top of the script.
- fzeindl 7mo agoI disable it only for the DIR variable which I might not use.
- aaravchen 7mo agoIt depends too on whether you use shellcheck as a primary tool or not. I prefer to have no shellcheck errors/warnings by default so when they do appear it's very obvious. But having a consistent opening block on a bunch of scripts is often more important, so setting a shellcheck disable on that one variable that may or may not be used is a better solution.
- a-french-anon 7mo agoI'd suggest `pwd -P` to resolve symlinks too. (if you use DIR to call/source neighbouring scripts).
- aaravchen 7mo agoIf you're using `set -e` you almost always want a trap on ERR to print where you suddenly exited from your program. Otherwise there's no way to tell. Also worth mentioning, but not including permanently, is `set -x` which will print every command to stderr with a `+ ` prefix before running it. For `DIR` I usually pick a name less likely to conflict with one randomly selected in my script, like `SCRIPT_DIR`. You also need to think about symlinks and how you want to handle them. Your current `DIR` resolution gives you the directory name without any symlinks resolved. If you're possibly a script that got symlinked to by someone, this may not be the directory of your actual script anymore, but the directory containing the symlink. As long as you want that it's fine, but a lot of the time you want the script to see it's resolved folder so it can call scripts in the real folder with it instead
- teh 7mo agoAnother useful "Emergency exit" is CTRL+Z which stops the process and cannot be intercepted. It's often faster than hitting CTRL+C and waiting for process cleanup, especially when many resources are used. Then you can do e.g. `kill -9 $(jobs -p)` to kill the stopped tasks.
- drzaiusx11 7mo agoctrl-z pauses the process, it doesn't terminate. I think of z as in zombie as you can then run fg to bring it back from paused state or as you suggested kill in it for good
- dasyatidprime 7mo agoAll of the keyboard-driven terminal signals can be intercepted; catching INT (^C) for cleanup is just more common than the others. Only KILL and STOP cannot be caught. ^Z sends TSTP (not STOP, though they have the same default behavior) to suspend; some programs catch this to do terminal state cleanup before re-raising it to accept the suspension. Catching it to do full backout doesn't make as much sense because the program anticipates being resumed. ^\ sends QUIT, which normally causes a core dump and is rarely caught. If you have core dumps disabled (via ulimit -c 0 or other system configuration) then you can often use it as a harder version of ^C; this is how I would tend to get out of ‘sl’ in places where I found it unwantedly installed.
- tzot 7mo agoFor the most simple case of a single job, I use the job number (`[1]` in the example) with %-notation for the background jobs in kill (which is typically a shell builtin): $ cat ^Z[1] + Stopped cat $ kill %1
- egorfine 7mo agoI'm using bash for over 30 years and I still find new things. Nice.
- elric 7mo agoRegarding history: I have a function in my ZSH config which excludes certain things from the history. Especially things that can break stuff when my sausage fingers CTRL-R the wrong thing Something like this: # Prevent certain strings from appearing in the history # Anything starting with a leading space is ignored # Anything containing "--force" or "whatever" is ignored function zshaddhistory() { emulate -L zsh if ! [[ "$1" =~ "(^ |--force|whatever)" ]] ; then print -sr -- "${1%%$'\n'}" fc -p else return 1 fi }
- rgrau 7mo agoThat's very cool! To take advantage of the "leading space" one, I have this, to mark some commands that I never want to record: unhist () { alias $1=" $1" } unhist unhist unhist fzf unhist rghist #custom command that greps .zhistory,...
- deleted 7mo ago[deleted]
- 0xcb0 7mo agoI've been using a lot of key combinations and I wasn't aware of these two, and I really think these are awesome additions to handling the console. Thank you for showing me. I've only been using it for 22 years, but I haven't come across these :D `CTRL + U and CTRL + K CTRL + W` What I like about these key combinations is that they are kind of universal. A lot of programs on Linux and Mac support all these key combinations out of the box. And that's like a game changer in productivity, especially jumping to the start or the end of the line or jumping forward and backward per word is making working only with the keyboard so much more nice. And in editors together so AVY, you can even get a faster flow of jumping around.
- antiframe 7mo agoYes, those are shortcuts used in the GNU readline library, which many programs use whenever they need to read lines of text interactively from their operators. Notable examples are (most) shells, (most) interpreters, and tools like ftp, fzf, etc. Notably, these keybindings are it's default map, which comes from the GNU's project editor Emacs. But, there is also the POSIX-compliant, but not-default, editing mode based on Bill Joy's visual editor (vi).
- williamcotton 7mo agoUndo: Ctrl + _ (Ctrl + underscore)
- bandie91 7mo agoit did not work for me in putty, so i added ctrl-x + ctrl-u too: bind '"\C-x\C-u": undo' bind '"\C-_": undo'
- alberto-m 7mo agoOne thing I find life-changing is to remap the up arrow so that it does not iterates through all commands, but only those starting with the characters I have already written. So e.g. I can type `tar -`, then the up arrow, and get the tar parameters that worked last time. In zsh this is configured with bindkey "^[OA" up-line-or-beginning-search # Up bindkey "^[OB" down-line-or-beginning-search # Down
- heresie-dabord 7mo ago> life-changing For further life-changing experience... add aliases to .bash_aliases alias gph='history | grep --colour -i ' alias gpc='grep --colour -Hin ' #if gnu time is installed alias timef='/usr/bin/time -f "tm %E , cpu %P , mem %M" '
- TacticalCoder 7mo agoI've got many like these I copied from various people over the years. One I came up and that I use all the time: alias wl='wc -l' I use it so much I sometimes forget it's not stock.
- bwhaley 7mo agoOnce you start using CTRL+r, you may find that you never reach for up arrow again.
- kuschkufan 7mo agoAnd once you want to one-up this look into fzf.
- nidnogg 7mo agoAnd once you get tired of fzf and want something better, you reach for https://atuin.sh https://atuin.sh. Completely transformed all of my workflows
- 7mo ago
- ruptwelve 7mo agoMaybe not a shell trick per-se but I have been a very big fan of zoxide. It can jump around your common directories. If you have a ~/workspace/projects and you are anywhere and type `cd projects` it will take you to that directory. I never realized how much I got hooked onto it, until I used a system without it.
- llarsson 7mo agoBuilt in functionality that may offer something similar: https://linuxhandbook.com/cdpath/ https://linuxhandbook.com/cdpath/
- jazoom 7mo agoI just type "z p" in that case and that's enough to get me there.
- aaravchen 7mo agoFor me I find I never have any reason to jump between directories based on frecency. Like ever. If I'm jumping between a few directories they're almost always named very similarly and that causes problems with the frecency ordering, especially when they're deep paths that get truncated. If I really happen to be jumping back and forth a lot, I use `pushd ...`, and then I can reference my other directory with `~1/` and toggle between the two with a bare `pushd`.
- TheServitor 7mo agogreat list but really overboard on the AI generated persona
- void-star 7mo agoset -o vi <esc> puts you into vi mode at the cli prompt with all the semantics of the editor. These carpal tunnel riddled hands can’t be bothered to reach for ctrl or alt let alone arrow keys.
- cess11 7mo agoIf you aren't aware already, you can put 'setxkbmap -option ctrl:swapcaps' in one of your startup config files, like .bashrc or somesuch. That flips left CTRL and CAPS LOCK.
- coopykins 7mo agoMy favourite QoL improvement to any shell I use is to improve the history function(Ctlr+R)I personally like https://github.com/cantino/mcfly https://github.com/cantino/mcfly
- Walf 7mo agoThe utility of $_ is often voided by tab-completion in the subsequent command, at least in bash. You won't know what it contains, which makes it dangerous, unless you first check it in a way that also carries it forwards: printf %s\\n "$_"
- piekvorst 7mo agoEven without tab completion, the variable can hold unexpected values due to user error (you don't see the command as a whole), multiple shell windows, or forgotten context. Relying on it even in limited scenarios can train an invisible habit that would backfire at the least expected moment. Any assistance intended for immediate action should itself be immediate, not indirect.
- fp64 7mo agoHere's my favorite tip: If you use bash, you can write bash on your prompt (duh). But this is one of the biggest reasons I stick with bash everywhere, as I am quite comfortable and experienced in bash and sometimes it's just easier to write things like `for i in *.mp3; do ffmpeg -i $i ...` etc. If it's re-usable, I write it to a bash script later.
- integralid 7mo agoThat's vaccously true as you said isn't it? I write fish on my shell and then I can save it as a fish script. Worth noting that bash is much more portable and available by default, but if I'm going for portability I go straight to /bin/sh
- fp64 7mo agoFair point, but for scripting I don't feel fish (or zsh) offer an advantage big enough to bother learning that language with their rather narrow scope. But bash it's good to anyways know, you don't really get around it either. Larger/more complex scripts I write in other languages (depending on domain I and other requirements I guess). It's also not that I daily write those scripts on my shell, so I also think that even if I learned fish or zsh, I would have to look up things again every time I need to write something again.
- martinflack 7mo agoI use `!!` quite a bit to repeat the output of the prior command as an argument. # it's in my PATH but can't remember where which myscript vi `!!`
- kleiba 7mo agoJust recently, I came up with this in my .bashrc, basically a "deep cd" command: dcd() { # If no argument is given, do nothing [ -z "$1" ] && return # Find the first matching directory under the current directory local dir dir=$(find . -type d -path "*$1*" -print -quit 2>/dev/null) # If a directory was found, cd into it [ -n "$dir" ] && cd "$dir" } I thought this would be way too slow for actual use, but I've come to love it.
- SoftTalker 7mo agoI knew most of these but the $_ variable and "ESC + ." to reference or insert the last argument of the previous command. I can see getting some use out of that, so thanks for posting.
- t312227 7mo agoor - as an alternative to <esc> + ".": for the last argument * <alt> + "." if you want the -<n>th argument: * <alt> + "_" # n times :=) * <alt> + "." cheers a..z
- arttaboi 7mo ago"cd -" is a lifesaver. Thank you so much for this.
- gchamonlive 7mo agoFor me the ultimate trick is to open the current prompt in vim with F2 (Ctrl+X ctrl+E seems to work too): # Use F2 to edit the current command line: autoload -U edit-command-line zle -N edit-command-line bindkey '^[OQ' edit-command-line # f2 is ^[OQ; to double check, run `xargs` and then press f2
- tzot 7mo ago> # f2 is ^[OQ; to double check, run `xargs` and then press f2 I remember using `cat -v` before learning that `xargs` exists… or maybe before `xargs` actually existed on systems I used :)
- chinadata 7mo agoonly the people do not use pageup and pagedown is who really know how to use shell
- olejorgenb 7mo agoDo yourself a favor and upgrade your history search with fzf shell integration (or similar): https://youtu.be/u-qLj4YBry0?t=223 https://youtu.be/u-qLj4YBry0?t=223 / https://junegunn.github.io/fzf/shell-integration/ https://junegunn.github.io/fzf/shell-integration/
- gaws 7mo agoOr use atuin[1] [1]: https://atuin.sh/ https://atuin.sh/
- scuff3d 7mo agoGreat write up, had to bookmark so I can go through it more later there so much good stuff in there. For the CTRL + R tip, you can make it even better if you install fzf. Massively improves searching through history. It's worth the install just for that one feature. Best thing I ever did as a dev was start spending more time in the terminal. Getting familiar with the tools and how they interact makes life so much easier.
- rdevilla 7mo agoset -o vi
- thibran 7mo agoIts almost ironical that we still use the Terminal - and many use it like in the eighties using Bash - and seem to have forgotten that we should invent a better terminal & shell than doing all the workarounds to handle the quirks of the current systems.
- mmh0000 7mo agoMake a better system, and we'll consider using it. A Terminal + Bash/ZSH is soooo sticky because they are VERY good at what they do once you learn the basics and quirks. And now with LLMs, CLIs are even better because LLMs talk in text and CLIs talk in text. Microsoft tried with PowerShell to design a better system; it "technically" is better, but not "better enough" to justify the cost of switching (on Linux). The same is true of nushell; it is "better", but not better enough to justify switching for most people. I believe we're at "peak input method" until someone invents Brain<->Computer interfaces.
- thibran 7mo agoI use the Terminal all the time and write my own CLI tools, but I'm feeling more and more the limits of the current system. With the years I have used almost all available shells (EShell was even my default for some time). Right now my favorite shell is Nushell, but still, it feels dated compare to what is possible on modern computers. > Make a better system, and we'll consider using it. It's on my TODO list, but it will break with all conventions and tools (no TTY). My idea is to bring the chain-things-together idea to the 21st century using a keyboard first GUI.
- bigstrat2003 7mo agoPowershell and nushell are both miles better than bash and its descendants. I switched to nushell and you couldn't pay me to go back to bash. I only wish that it was kosher to install it on servers at work, but alas it isn't so I have to suffer with bash when managing systems.
- bigstrat2003 7mo agoWe did! Nushell and Powershell are both so much better than bash that it's not even funny. There's zero reason to use a bash derivative in this day and age, they only persist through inertia + a minority of masochists actually like bash.
- MattGrommes 7mo agoIf only somebody had a lifehack for making me remember all these awesome commands. If I do something the slow way it's usually because I don't do the operation enough to burn it into my memory, or I got burned by accidentally hitting something close but incorrect once and closed the tab or something.
- w-ll 7mo agopost-it note until you dont need it anymore
- shigawire 7mo agoI hate to be the AI guy, but a coach that lived in my terminal and corrected me when I do it the slow way would actually help.
- stevthegouws 7mo agoI find spaced repetition Anki flash cards surpisingly effective for this kind of thing. You’d think remembering tonnes of shortcuts and commands and flags would be alot of effort but it’s surprisingly low effort when using cloze deletions and phrased like: - “… is to delete the last word” - “Ctrl w is to …” If you’re not familiar with spaced repetition it’s worth checking out, especially if you have a holey memory like mine. https://ncase.me/remember/ https://ncase.me/remember/
- stormed 7mo agoYou'll look like the coolest person in the office running `sudo !!`. Another personal favorite of mine is using the --now flag for systemctl to enable & start a service in one command (i.e `systemctl enable --now nginx`)
- tzot 7mo agoOn scripts that might handle filenames with spaces, I include: IFS=' '' ' Hint: the spaces between the first two apostrophes are actually one <Tab>. This does not affect the already written script (you don't need to press Tab instead of space to separate commands and arguments in the script itself), but by making <Tab> and <LF> be the “internal field separators” will allow globbing with less quoting worries while still allowing for `files=$(ls)` constructs. Example: IFS=' '' ' echo hello >/tmp/"some_unique_prefix in tmp" cat /tmp/some_unique_prefix* fn="My CV.txt" echo "I'm alive" >/tmp/$fn cat /tmp/$fn Of course this will still fail if there happens to be a filename with <Tab> in it.
- piekvorst 7mo agoI can't reproduce the glob expansion problem. % echo test >'/tmp/hello world' % cat /tmp/hello* test This is bash 5.3.9. Still, I couldn't agree more on limiting IFS. Personally, I set it only to <LF>. In my scripts, I rely on the $(ls) idiom heavily. People I've talked to consider this an anti-pattern and suggest relying on -0, -z, --zero, --null, and -print0 flags instead. I don't deny that it's better than nothing when correctness is the goal, but I’d counter that shell is more about using a familiar interface (text representation) to solve new tasks, not about writing correct code (that’s the domain of other languages). An uncritical pursuit of correctness often results in convoluted code. (I know that $(ls) is a subject to various expansions. I solve this problem by using a shell that doesn't do that [1].) Another consideration is that /bin/ls and /bin/find are not the only sources of filenames. Sometimes the source is third-party or has to be user-friendly (and thus separated by traditional newlines). Some typographical issues just can't be solved by a pursuit of mechanistic correctness. For another example, the \.txt$ idiom wouldn't work if spaces are allowed at the end of filenames. Those problems are not even shell-specific. Those are just a few of my personal notes. Fortunately, there's a more systematic and comprehensive study of this issue [2]. [1]: https://9p.io/sys/doc/rc.html https://9p.io/sys/doc/rc.html [2]: https://dwheeler.com/essays/fixing-unix-linux-filenames.html https://dwheeler.com/essays/fixing-unix-linux-filenames.html
- alkh 7mo agoThis snippet for zsh still has some rough edges but works for the majority of cases. Automatically extends any global alias when space is pressed in zsh. For ex. I have `alias -G G='rg -s'`, so if I type `command | G` it will autoexpand it to `command | rg -s` and so on. globalias() { local raw word # raw last blank-separated token, exactly as typed raw=${LBUFFER##\* } # shell-parsed last word word=${${(z)LBUFFER}[-1]} # if user typed \alias, don't expand if [[ $raw == \\* ]]; then zle self-insert return fi if alias -- ${(q)word} &>/dev/null; then zle _expand_alias zle expand-word fi zle self-insert } zle -N globalias bindkey ' ' globalias
- nickjj 7mo agoCTRL+L isn't the same as clear btw, it really maps back to `clear -x`. CTRL+L clears the visible output but you can still scroll up in your buffer to see the rest, clear will clear that scroll up buffer too. I've written about and demo'd this in https://nickjanetakis.com/blog/clear-vs-ctrl-l-in-your-shell https://nickjanetakis.com/blog/clear-vs-ctrl-l-in-your-shell.
- kwar13 7mo agothat was fantastic, learned a couple things after all these years too. alt+. ftw
- annie511266728 7mo agoThe annoying part is not learning these, it’s remembering them at the right time. I’ve started keeping a tiny cheatsheet just to avoid rediscovering the same tricks over and over.
- aaravchen 7mo agoI try to keep a list somewhere, but I only pick one or two that are likely to be most useful and try to remember them until they're such a normal part of my workflow I don't have to think much about them anymore. Then I go back and pick a couple new ones to add. The hard part is when you've reached the point where all your common use cases are covered and you're left with only uncommon cases. Then it's extra hard to remember you had a trick for dealing with the uncommon case.
- smcameron 7mo agoOn the "reset"/"stty sane" trick, I also sometimes have found it necessary to press Ctrl-J rather than RETURN at the end of the command.
- rurban 7mo agoDidnt know about disown. Great, no more nohup
- aaravchen 7mo ago`set -e` is almost never what you want in your scripts. It means "silently exit immediately if there are any u handled non-zero exit codes". The thing that trips most people up on that is subshells when your trying to catch output into a variable, if it gets a non-zero exit code your entire script suddenly exits. `set -e` really only makes sense if you setup a trap to also print what line you exited on, and even then only for debugging (e g. `trap 'echo "ERROR: Line $LINENO" ERR'`) Conversely, `set -o pipefail` should be set in every script. It makes scripts with pipelines do what you expect, and the whole string of pipeline commands gets set to an error if any of the commands inside of it exit with an error. Default behavior for historical reasons is still to ignore all exit codes except the last command in a pipeline.
- zzo38computer 7mo agoCTRL+C will send a interrupt signal; in some programs (and some circumstances in some programs) that does not work, but then you might try CTRL+\ which will send a quit signal; sometimes that works even if interrupt does not work.