[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)