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