[HN Gopher] Bash-oneliner: A collection of handy Bash one-liners...
       ___________________________________________________________________
        
       Bash-oneliner: A collection of handy Bash one-liners and terminal
       tricks
        
       Author : bfm
       Score  : 199 points
       Date   : 2022-05-03 16:31 UTC (6 hours ago)
        
 (HTM) web link (github.com)
 (TXT) w3m dump (github.com)
        
       | abetusk wrote:
       | I love these one-liners. It's also about knowing your tools
       | better.
       | 
       | I hadn't known about `look` [0], which is great.
       | 
       | The writer looks to be a bioinformatician, so it might be a bit
       | out of scope, but I also found `socat` [1] quite a good serial
       | communication helper tool.
       | 
       | [0] https://man7.org/linux/man-pages/man1/look.1.html
       | 
       | [1] https://linux.die.net/man/1/socat
        
         | mxuribe wrote:
         | I don't recall where I heard it, but my understanding is that
         | socat is the sort of successor to good ol' netcat. (Of course,
         | don't ask me to compare each, nor know what socat brings that
         | netcat lacks, etc.)
        
           | abetusk wrote:
           | `socat` is netcat but for serial. [0]
           | 
           | [0] https://serverfault.com/questions/246347/whats-the-
           | differenc...
        
             | mxuribe wrote:
             | Oooohhh!
        
             | teddyh wrote:
             | No, socat is for _sockets_ , not for "serial".
        
         | mdaniel wrote:
         | And, fun fact, "socat" is how "kubectl port-forward" works so
         | it'll likely be present on any machine behaving as a kubernetes
         | Node
        
       | archielc wrote:
       | That's a nice and very extensive collection.
       | 
       | As a follow-up, I can also recommend Effective Shell series. I
       | used to have navigation shortcut diagram from Part 1
       | (https://dwmkerr.com/effective-shell-part-1-navigating-the-co...)
       | printed out.
        
         | bfm wrote:
         | Thanks for sharing, I love the animations and diagrams.
        
         | hn_user82179 wrote:
         | Thank you so much for the navigation shortcut link! I love
         | these and picked them up from mentors at jobs but never found a
         | definitive guide to all of the ones I could learn.
        
       | hamosch wrote:
       | Learnt a neat trick from an old sysadmin colleague.
       | 
       | If you've written a command but realize you don't want to run it
       | right now but want to save it in your history you can just put a
       | `#` in front of it (ctrl-a #) making it a comment and allowing
       | you to save it in your history without running it.
       | 
       | When you're ready to run it you find it and remove the preceding
       | `#`
        
         | panki27 wrote:
         | You can achieve the same thing by typing a command, then
         | hitting Escape followed by '#'.
         | 
         | It will prefix your current commandline with a '#' and "run"
         | it.
        
         | 1vuio0pswjnm7 wrote:
         | This is useful when saving command lines to files (scripts)
         | using the POSIX-required fc builtin. Command line histories are
         | relatively cumbersome to save with Ash, Bash saves them but
         | truncates them to 500 entries, whereas scripts can easily be
         | saved indefinitely. Amongst Bash and other feature-heavy shell
         | users, there are Rube Goldberg-like workarounds for command
         | line history saving. OTOH, all shells aiming for POSIX
         | compliance, including the fastest, lightest weight ones I
         | prefer, will implement fc. It's already there; I make use of
         | it.
         | 
         | I will type fc, save to a file (script) and then delete all
         | lines before exiting the default EDITOR, e.g., %d in vi. This
         | prevents the commands from being re-executed when I exit vi.
         | 
         | Also I sometimes use # combined with a semicolon to disable
         | portions of command lines, e.g., early commands ;# late
         | commands. I might cut and paste from one entry in the history
         | into another one. Or I might fc -l 1 > file and edit the file
         | down the the entries that form the starting point for a new
         | script. By far, the shell is the most useful REPL for me.
         | 
         | There is no shortage of comments online praising the utility of
         | the REPL concept but the only comment I have ever seen about fc
         | was from a shell implementor/maintainer; it was negative. I use
         | fc all the time. It has become essential for me to use the
         | shell effectively as a REPL.
        
         | bananskalare wrote:
         | alt-# is quite enough.
        
         | archielc wrote:
         | The opposite is adding space before the command. The command
         | will run but it will not be saved in history.
         | 
         | EDIT: This apparently needs to be configured - setting
         | HISTCONTROL=ignorespace
        
           | pseudostem wrote:
           | Thanks to your comment, I learnt about ignoredups as well
        
             | matijs wrote:
             | And `ignoreboth` to combine the two.
        
           | KMag wrote:
           | I had been in the habit of symlinking ~/.bash_history to
           | /dev/null to avoid AFS/NFS writes on every local command
           | execution. When I moved over to the financial industry, it
           | didn't occur to me that such a symlink might look like an
           | attempt to evade monitoring. A year or two in, I realized it
           | didn't look good, but it had clearly been made my first week
           | on the job, so I just left it in place for over 10 years
           | rather than risk looking like I was again monkeying with my
           | history.
           | 
           | I hope and presume they had much better monitoring than
           | scanning bash history, but I'm not bet-my-career confident of
           | that.
        
             | JetSpiegel wrote:
             | It's simpler to use a tmpfs for this purpose.
             | $XDG_RUNTIME_DIR is already available, on modern Linux
             | versions.
        
         | C4K3 wrote:
         | I wonder if it isn't possible to get it to save your command to
         | history when you do Ctrl-C.
         | 
         | I tried a naive way by trapping sigint but couldn't get it to
         | work.
        
         | kappattack wrote:
         | Lol that makes sense, never thought of commenting out the
         | command but I guess I do something similar. If i realize i dont
         | want a command yet I enter it with a trailing `\\`, then
         | `CTRL+C` to get back to an empty prompt.
        
       | bfm wrote:
       | Not one-liners, but some of the tools that I have found helpful
       | for working with large bash codebases are:                 -
       | shellcheck and shfmt for linting and formatting       - sub for
       | organizing subcommands       - bashdb for debugging scripts
       | interactively via the VSCode extension
       | 
       | I'm still missing a way to share modules with others like it can
       | be done with ansible/terraform, but I have not found an optimal
       | way to do it yet.
       | 
       | [shellcheck] https://github.com/koalaman/shellcheck [shfmt]
       | https://github.com/mvdan/sh [sub] https://github.com/qrush/sub
       | [bashdb] http://bashdb.sourceforge.net/ [vscode-bash-debug]
       | https://github.com/rogalmic/vscode-bash-debug
        
       | arittr wrote:
       | this is awesome, great work. this is really the first time i've
       | opened up one of these "awesome list of X" repos and immediately
       | learned a ton.
       | 
       | required reading for the bash newbie and mage alike. 10/10 will
       | reference again and again.
        
       | mdaniel wrote:
       | sed -i
       | 
       | Watch out, that's a Linux-ism and macOS's sed will cheerfully use
       | the thing after it as the backup expression; as far as I know,
       | the absolute safest choice is to always specify a backup
       | extension "sed -i~" or "sed -i.bak" to make it portable, although
       | there are plenty of work-arounds trying to detect which is which
       | and "${SED_I} -e whatever" type silliness
       | 
       | My contribution (and yeah, I know, PR it ...) is that I get a lot
       | of mileage out of setting the terminal title from my scripts:
       | title() { printf '\033]0;%s\007' "$*"; }
       | 
       | and there's one for tmux, too                   printf
       | '\033]2;%s\007' "$*";
       | 
       | with the two infinitely handy resources:
       | 
       | * https://www.xfree86.org/current/ctlseqs.html
       | 
       | * https://iterm2.com/documentation-escape-codes.html
        
         | gnubison wrote:
         | Even better, use a real text editor like ed or ex. (Nowadays ex
         | is more portable because many distros -- against POSIX -- omit
         | all 55 kilobytes of GNU ed. Of course, smaller systems might
         | not have ex/vi.)
         | 
         | Basic usage looks like this:                   printf '%s\n' '"
         | some commands...' 'wq' | ex -s file
         | 
         | Or:                   ex -s file <<'EOF'         " some
         | commands...         wq         EOF
         | 
         | By the way, these commands are the ones that you use in your
         | vimrc or after a colon in vim -- at least, the POSIX subset of
         | that -- so any ex commands you learn translate naturally to
         | your normal editor.
        
           | mdaniel wrote:
           | That's an interesting trick, I'll bear it in mind.
           | 
           | That said, the "lottery factor" is often a bigger contributor
           | to the things that land in codebases than "optimality". Plus,
           | I've actually seen somewhere that perl is the most common
           | binary across every system, and it's likely a larger
           | population who know perl than ed would be my guess
        
             | gnubison wrote:
             | Perl more common than vi? The study you're remembering
             | probably didn't include POSIX utilities.
        
               | mdaniel wrote:
               | With the full understanding that "docker images" are
               | their own special little things:                   $
               | docker run --rm ubuntu:22.04 bash -c 'command -v ex;
               | command -v ed; command -v vi; command -v perl;'
               | /usr/bin/perl
               | 
               | and the same result for "debian:stable"
               | 
               | ---
               | 
               |  _edit:_ I just realized that 's because apt is _written
               | in_ perl, but tomato, tomahto, and it may very well be
               | that they picked perl for that same universal-binary
               | reason
        
         | teddyh wrote:
         | Using raw escape codes is ugly and device-dependent. People
         | learned this in the 1970's, and created libraries to get _away_
         | from having to hard-code escape codes.
         | 
         | Here's a device-independent variant:                 title(){
         | tput tsl || tput -T xterm+sl tsl; printf %s "$*"; tput fsl ||
         | tput -T xterm+sl fsl; }
         | 
         | Note: if the terminal does not advertise support of the
         | necessary capabilities, it falls back to using the XTerm escape
         | sequences.
        
         | ancientsofmumu wrote:
         | > _Watch out, that 's a Linux-ism and macOS's sed_
         | 
         | It's GNU sed vs (Free)BSD sed, which are different enhancements
         | of the POSIX standards for sed that went in different design
         | directions. One could Homebrew/macports install gnu-sed on
         | macOS to get a GNU version to write Linux-portable scripts as-
         | needed.
        
           | 1vuio0pswjnm7 wrote:
           | Plan9 sed has no -i option. Older versions of NetBSD will not
           | have it either.
           | 
           | I never understood the point of the -i option other than to
           | conserve keystrokes. Maybe there is some other advantage I
           | have failed to notice. A temporary file is still created then
           | removed; the -i option only saves the user from having to
           | specify it.
           | 
           | This will work for GNU, BSD and Plan9:                  sed
           | -n 's/old/new/wfile.tmp' file        mv file.tmp file
           | 
           | Given the choice between avoiding some keypresses and having
           | a more portable script, I will choose the later.
        
           | 1vuio0pswjnm7 wrote:
           | Plan9 sed has no -i option. Older versions of NetBSD will not
           | have it either.
           | 
           | I never understood the point of the -i option other than to
           | conserve keystrokes. A temporary file is still created then
           | removed; the -i option only saves the user from having to
           | specify it.
           | 
           | This will work for GNU, BSD and Plan9:                  sed
           | -n 's/old/new/wfile.tmp' file        mv file.tmp file
           | 
           | Given the choice between avoiding some keypresses and having
           | a more portable script, I will choose the later.
        
             | mdaniel wrote:
             | Yeah, I've heard that argument, too, but I fear that ship
             | has sailed
             | 
             | Also, be aware you currently have duplicated comments:
             | https://news.ycombinator.com/item?id=31254181
        
         | cglong wrote:
         | Yeah please do open PRs for these!
        
       | mgr86 wrote:
       | > Ctrl + x + Ctrl + e : launch editor defined by $EDITOR to input
       | your command. Useful for multi-line commands. --
       | 
       | Great, I was just trying to remember that key combination the
       | other day. Just got back to work after being for awhile for a
       | child bonding leave.
        
       | tambourine_man wrote:
       | Something I've been wanting to do but haven't found a perfect
       | solution for yet: storing the output of previous command in some
       | variable by default.
       | 
       | I use Terminal.app's Select Between Marks or tmux, but I wish
       | this was a thing.
        
         | quesera wrote:
         | You can use:                 VAR=$(!!)
         | 
         | to accomplish something similar. Not by default of course.
         | 
         | It re-runs the command, so if not idempotent/etc it will not
         | return expected results. Also when re-run, the command will not
         | be in a tty context, so if the executable is sensitive to such
         | things (e.g. `ls`), the output format might be different.
        
           | tambourine_man wrote:
           | Yeah, I know, but I don't want to re-run and I want it by
           | default.
        
         | yakshaving_jgt wrote:
         | Perhaps you could change your prompt so that everything is
         | wrapped with tee.
         | 
         | Interesting rabbit hole to go down...
         | 
         | https://unix.stackexchange.com/q/562018
        
       | chasil wrote:
       | New users on my systems commonly ask me "what implements your pps
       | process search?"
       | 
       | When the shell itself filters the output of ps, then removing a
       | grep is unnecessary. Note this uses POSIX shell patterns, not
       | regular expressions.
       | 
       | On a truly POSIX shell that does not support "local," remove the
       | keyword, and change the braces to parentheses to force the
       | function into a subshell.                 pps () { local a= b= c=
       | IFS='\0'; ps ax | while read a         do [ "$b" ] || c=1; for b;
       | do case "$a" in *"$b"*) c=1;;           esac; done; [ "$c" ] &&
       | printf '%s\n' "$a" && c=; done; }            $ pps systemd
       | PID TTY      STAT   TIME COMMAND           1 ?        Ss     5:11
       | /usr/lib/systemd/systemd --switched-root --system --deserialize
       | 22         557 ?        Ss     0:19 /usr/lib/systemd/systemd-
       | journald       ...
        
       | dangom wrote:
       | Great training dataset for copilot.
        
       | archduck wrote:
       | I was surprised to see `$()` missing from this (otherwise quite
       | extensive) list. There are a few commands listed which employ it,
       | but it absolutely deserves its own entry.
       | 
       | That and `readlink -f` to get the absolute path of a file.
       | (Doesn't work on MacOS; the only substitute I've found is to
       | install `greadlink`.)
       | 
       | And `cp -a`, which is like `cp -r`, but it leaves permissions
       | intact - meaning that you can prepend `sudo` without the hassle
       | of changing the ownership back.
       | 
       | I never see `lndir` on these lists either. It makes a copy of a
       | directory, but all of the non-directory files in the target are
       | replaced with symlinks back to the source while directories are
       | preserved as-is. Meaning that when you `cd` into it, you are
       | actually landing in a copied structure of the source directory
       | instead of the source directory itself, as would be the case if
       | you just symlinked the source folder.
       | 
       | Once inside, any file you want to modify without affecting the
       | original just needs you to create the symlink into a file, which
       | you can do with `sed -i '' $symlink`. There you have it:
       | effectively a copy of your original directory, with only the
       | modified files actually taking up space (loosely speaking).
       | 
       | Looks like I have a few pull requests to submit.
        
         | hummusFiend wrote:
         | FWIW `realpath` on macOS should be functionally equivalent to
         | `readlink -f` - particularly if you ignore all the other
         | functionality `readlink` provides.
        
         | ineedasername wrote:
         | _> a copy of your original directory, with only the modified
         | files actually taking up space_
         | 
         | What's the use case for this sort of thing?
        
           | gizmo686 wrote:
           | At work, we have a codebase that is used by numerous
           | projects. The solution for project specific changes is
           | 'checkout the repo, and make your changes locally'.
           | 
           | What that has turned into is 'checkout the repo and make a
           | new directory structure that symlinks everything back to the
           | original'. The keeps the maintenance burden relatively small
           | as you can easily update the base version, and only need to
           | worry about the files you changed.
           | 
           | I certainly wouldn't recommend using this approach for
           | anything; but it is not as terrible as it sounds.
        
           | archduck wrote:
           | When I need to shuffle around and/or rename my media files,
           | for instance, it's risky to operate on the originals
           | themselves. I've screwed up hundreds of mp3 files by issuing
           | a bad `rename` command. I've lost the hierarchical structures
           | of genres and artists and albums and such by accidentally
           | moving them into the same directory together. And so on.
           | 
           | If you `lndir` your mp3 directory to a functional copy of it,
           | a playground of sorts, you can move things around and rename
           | them without having to worry about scenarios like having to
           | listen to a bunch of mp3s in order to put them back to where
           | they're supposed to be.
           | 
           | When you're satisfied with the re-organization of your files,
           | you can replace your symlinks with the original files. Since
           | none of the directories are symlinked, you never have to
           | worry about `cd`ing into a place you didn't intend to.
        
       ___________________________________________________________________
       (page generated 2022-05-03 23:00 UTC)