sed -n 2p file
prints the second line of file. The advantage sed has over this line script is it can also print more than one line, should you need to: sed -n 2,4p file
prints lines 2 through 4, inclusive.What's always interesting to me is how many of these I'll see and initially think, "I don't really need that." Because I'm well aware of the effect (which I'm sure has a name - I suppose it's similar to induced demand) of "make $uncommon_task much cheaper" -> "$uncommon_task becomes the basis of an entirely new workflow/skill". So I'm going to try out most of them and see what sticks!
Also: really love the style of the post. It's very clear but also includes super valuable information about how often the author actually uses each script, to get a sense ahead of time for which ones are more likely to trigger the effect described above.
A final aside about my own workflows which betrays my origins... for some of these operations and for others i occasionally need, I'll just open a browser dev tools window and use JS to do it, for example lowercasing a string :)
A password or token generator, simple or complicated random text.
Scripts to list, view and delete mail messages inside POP3 servers
n, to start Nautilus from terminal in the current directory.
lastpdf, to open the last file I printed as PDF.
lastdownload, to view the names of the n most recent files in the Downloads directory.
And many more but those are the ones that I use often and I remember without looking at ~/bin
- When I was a fresh engineer I used a pretty vanilla shell environment
- When I got a year or two of experience, I wrote tons of scripts and bash aliases and had a 1k+ line .bashrc the same as OP
- Now, as a more tenured engineer (15 years of experience), I basically just want a vanilla shell with zero distractions, aliases or scripts and use native UNIX implementations. If it's more complicated than that, I'll code it in Python or Go.
sed, awk, grep, and xargs along with standard utilities get you a long long way.
Which often just confuses things further.
Me: My name is "Farb" F-A-R-B. B as in Baker.
Them: Farb-Baker, got it.
Now I have many nix computers and I want them consistent and with only the most necessary packages installed.
Personally I tend to agree... there is a very small subset of things I find worth aliasing. I have a very small amount and probably only use half of them regularly. Frankly I wonder how my use case is so different.
edit: In the case of the author I guess he's probably wants to live in the terminal full time. And perhaps offline. there is a lot of static data he's stored like http status codes: https://codeberg.org/EvanHahn/dotfiles/src/commit/843b9ee13d...
In my case i'd start typing it in my browser then just click something i've visited 100 times before. There is something to be said about reducing that redundant network call but I dont think it makes much practical difference and the mental mapping/discoverability of aliases isnt nothing.
Otherwise, I am happy to be pulled into your discussion, Marshall McLuhan style[3] to adjudicate, for a very reasonable fee.
[1] https://craphound.com/lifehacksetcon04.txt
[2] https://archive.org/details/Notcon2004DannyOBrienLifehacks
[3] https://www.openculture.com/2017/05/woody-allen-gets-marshal...
Nowadays I just try to be quite selective with my tooling and learn to change with it - "like water", so to speak.
(I say this with no shade to those who like maintaining their dotfiles - it takes all sorts :))
For example. The "saves 5 seconds task that I do once a month" from the blog post. Hopefully the author did not spend more than 5 minutes writing said script and maintaining it, or they're losing time in the long run.
The way you’re doing it trashes files sequentially, meaning you hear the trashing sound once per file and ⌘Z in the Finder will only restore the last one. You can improve that (I did it for years) but consider just using the `trash` commands which ships with macOS. Doesn’t use the Finder, so no sound and no ⌘Z, but it’s fast, official, and still allows “Put Back”.
> jsonformat takes JSON at stdin and pretty-prints it to stdout.
Why prioritise node instead of jq? The latter is considerably less code and even comes preinstalled with macOS, now.
> uuid prints a v4 UUID. I use this about once a month.
Any reason to not simply use `uuidgen`, which ships with macOS and likely your Linux distro?
Like, it's okay -- even good -- for the tools to bend to the user and not the other way around.
I have almost the same, but differently named with scratch(day), copy(xc), markdown quote(blockquote), murder, waitfor, tryna, etc.
I used to use telegram-send with a custom notification sounnd a lot for notifications from long-running scripts if I walked away from the laptop.
I used to have one called timespeak that would speak the time to me every hour or half hour.
I have go_clone that clones a repo into GOPATH which I use for organising even non-go projects long after putting go projects in GOPATH stopped being needed.
I liked writing one-offs, and I don't think it's premature optimization because I kept getting faster at it.
You can configure your shell to notify the terminal of directory changes, and then use your terminal’s “open new window” function (eg: ctrl+shift+n) to open a new window retaining the current directory.
mkdir /some/dir
cd !$
(or cd <alt+.>)
as a person who loves their computer, my ~/bin is full. i definitely (not that you said this) do not think "everything i do has to be possible on every computer i am ever shelled into"
being a person on a computer for decades, i have tuned how i want to do things that are incredibly common for me
though perhaps you're referring to work and not hobby/life
When I watch the work of coworkers or friends who have gone these rabbit holes of customization I always learn some interesting new tools to use - lately I've added atuin, fzf, and a few others to my linux install
I use this as a bookmarklet to grab the front page of the new york times (print edition). (You can also go back to any date up to like 2011)
I think they go out at like 4 am. So, day-of, note that it will fail if you're in that window before publishing.
javascript:(()=>{let d=new Date(new Date().toLocaleString('en-US',{timeZone:'America/New_York'})),y=d.getFullYear(),m=('0'+(d.getMonth()+1)).slice(-2),g=('0'+d.getDate()).slice(-2);location.href=`https://static01.nyt.com/images/${y}/${m}/${g}/nytfrontpage/scan.pdf`})()
Anyways, my favourite alias that I use all the time is this:
alias a='nvim ~/.zshrc && . ~/.zshrc'
It solves the ,,not loaded automatically'' part at least for the current terminal #!/bin/sh
if test "$#" != 2
then
echo 'Error: unmv must have exactly 2 arguments'
exit 1
fi
exec mv "$2" "$1"
alias ..='cd ..'
alias ...='cd ../..'
alias ....='cd ../../..'
alias .....='cd ../../../..'
alias ......='cd ../../../../..'
alias .......='cd ../../../../../..'
up 2, up 3 etc.
I once had someone sound out a serial number over a spotty phone connection years ago and they said "N as in NAIL". You know what sounds a lot like NAIL? MAIL.
And that is why we don't just arbitrarily make up phonetic alphabets.
clippy image.png # then paste into Slack, etc. as upload
clippy -r # copy most recent download
pasty # copy file in Finder, then paste actual file here
https://github.com/neilberkman/clippy / brew install clippyHere are some super simple ones I didn't see that I use almost every day:
cl="clear"
g="git"
h="history"
ll="ls -al"
path='echo -e ${PATH//:/\\n}'
lv="live-server"
And for common navigation:
dl="cd ~/Downloads"
dt="cd ~/Desktop"
The amount of shit you'll get for "applying your dotfiles" on a client machine or a production server is going to be legendary.
Same with containers, please don't install random dotfiles inside them. The whole point of a container is to be predictable.
https://evanhahn.com/why-alias-is-my-last-resort-for-aliases...
$ cat /usr/local/bin/awkmail
#!/bin/gawk -f
BEGIN { smtp="/inet/tcp/0/smtp.yourco.com/25";
ORS="\r\n"; r=ARGV[1]; s=ARGV[2]; sbj=ARGV[3]; # /bin/awkmail to from subj < in
print "helo " ENVIRON["HOSTNAME"] |& smtp; smtp |& getline j; print j
print "mail from:" s |& smtp; smtp |& getline j; print j
if(match(r, ","))
{
split(r, z, ",")
for(y in z) { print "rcpt to:" z[y] |& smtp; smtp |& getline j; print j }
}
else { print "rcpt to:" r |& smtp; smtp |& getline j; print j }
print "data" |& smtp; smtp |& getline j; print j
print "From:" s |& smtp; ARGV[2] = "" # not a file
print "To:" r |& smtp; ARGV[1] = "" # not a file
if(length(sbj)) { print "Subject: " sbj |& smtp; ARGV[3] = "" } # not a file
print "" |& smtp
while(getline > 0) print |& smtp
print "." |& smtp; smtp |& getline j; print j
print "quit" |& smtp; smtp |& getline j; print j
close(smtp) } # /inet/protocol/local-port/remote-host/remote-port
In powershell I just do
> echo '{"foo": "bar"} | ConvertFrom-Json | ConvertTo-Json
{
"foo": "bar"
}
But as a function # ex - archive extractor
# usage: ex <file>
function ex() {
if [ -f $1 ] ; then
case $1 in
*.tar.bz2) tar xjf $1 ;;
*.tar.gz) tar xzf $1 ;;
*.tar.xz) tar xf $1 ;;
*.bz2) bunzip2 $1 ;;
*.rar) unrar x $1 ;;
*.gz) gunzip $1 ;;
*.tar) tar xf $1 ;;
*.tbz2) tar xjf $1 ;;
*.tgz) tar xzf $1 ;;
*.zip) unzip $1 ;;
*.Z) uncompress $1;;
*.7z) 7z x $1 ;;
*) echo "'$1' cannot be extracted via ex()" ;;
esac
else
echo "'$1' is not a valid file"
fi
}
clippy image.png # then paste into Slack, etc. as upload
Also: pasty # paste actual file, after copying file in Finder
I'm curious to hear some examples (feel like I'm missing out)
zsh: permission denied: ..
zsh: command not found: ...
Other single-key bindings I use often are:
KP* executes 'ls'
KP- executes 'cd -'
KP+ executes 'make -j `nproc`'
Like, I'd have to remember both `prettypath` and `sed`, and given that there's hardly any chance I'll not need `sed` in other situations, I now need to remember two commands instead of one.
On top of that `prettypath` only does s/:/\\n/ on my path, not on other strings, making its use extremely narrow. But generally doing search and replace in a string is incredibly useful, so I'd personally rather just use `sed` directly and become more comfortable with it. (Or `perl`, but the point is the same.)
As I said, that's obviously just my opinion, if loads of custom scripts/commands works for you, all the more power to you!
this fella doesn't know what "toggle" means. in this context, it means "turn off if it's currently on, or turn on if it's currently off."
this should be named `wifi cycle` instead. "cycle" is a good word for turning something off then on again.
naming things is hard, but it's not so hard that you can't use the right word. :)
alias vz="vim ~/.zshrc && . ~/.zshrc"
I alias mdfind to grep my .docx files on my Mac: docgrep() {
mdfind "\"$@\"" -onlyin /Users/xxxx/Notes 2> >(grep --invert-match ' \[UserQueryParser\] ' >&2) | grep -v -e '/Inactive/' | sort
}
I use an `anon` function to anonymize my Mac clipboard when I want to paste something to the public ChatGPT, company Slack, private notes, etc. I ran it through itself before pasting it here, for example. anonymizeclipboard() {
my_user_id=xxxx
account_ids="1234567890|1234567890" #regex
corp_words="xxxx|xxxx|xxxx|xxxx|xxxx" #regex
project_names="xxxx|xxxx|xxxx|xxxx|xxxx" # regex
pii="xxxx|xxxx|xxxx|xxxx|xxxx|xxxx" # regex
hostnames="xxxx|xxxx|xxxx|xxxx|xxxx|xxxx|xxxx|xxxx|xxxx" # regex
# anonymize IPs
pbpaste | sed -E -e 's/([0-9]{1,3})\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/\1.x.x.x/g' \
-e "s/(${corp_words}|${project_names}|${my_user_id}|${pii}|${hostnames})/xxxx/g" -e "s/(${account_ids})/1234567890/g" | pbcopy
pbpaste
}
alias anon=anonymizeclipboard
It prints the new clipboard to stdout so you can inspect what you'll be pasting for anything it missed.Folks interested in scripting like this might like this tool I'm working on https://github.com/amterp/rad
Rad is built specifically for writing CLI scripts and is perfect for these sorts of small to medium scripts, takes a declarative approach to script arguments, and has first-class shell command integration. I basically don't write scripts in anything else anymore.
Admittedly, I've toned down the configs of some programs, as my usage of them has evolved or diminished, but many are still highly tailored to my preferences. For example, you can't really use Emacs without a considerable amount of tweaking. I mean, you technically could, but such programs are a blank slate made to be configured (and Emacs is awful OOB...). Similarly for zsh, which is my main shell, although I keep bash more vanilla. Practically the entire command-line environment and the choices you make about which programs to use can be considered configuration. If you use NixOS or Guix, then that extends to the entire system.
If you're willing to allow someone else to tell you how you should use your computer, then you might as well use macOS or Windows. :)
alias mpa='mpv --no-video'
mpa [youtube_url]
I use this to listen to music / lectures in the terminal.I think it needs yt-dlp installed — and reasonably up to date, since YouTube keeps breaking yt-dlp... but the updates keep fixing it :)
ytsub() {
yt-dlp \
--write-sub \
--write-auto-sub \
--sub-lang "en.*" \
--skip-download \
"$1" && vtt2txt
}
ytsub [youtube_url]
Where vtt2txt is a python script — slightly too long to paste here — which strips out the subtitle formatting, leaving a (mostly) human readable transcript.Does all the right things and works great.
There’s a similar tool that works well on Linux/BSDs that I’ve used for years, but I don’t have my FreeBSD desktop handy to check.
The Mac Shortcut at https://github.com/e-kotov/macos-shortcuts lets you select a particular area of the screen (as with Cmd-Shift-4) and copies the text out of that, allowing you to copy exactly the text you need from anywhere on your screen with one keyboard shortcut. Great for popups with unselectable text, and copying error messages from coworkers' screenshares.
The flags are for maximum compatibility (e.g. without them, some MP4s don't play in WhatsApp, or Discord on mobile, or whatever.)
ffmp4() {
input_file="$1"
output_file="${input_file%.*}_sd.mp4"
ffmpeg -i "$input_file" -c:v libx264 -crf 33 -profile:v baseline -level 3.0 -pix_fmt yuv420p -movflags faststart "$output_file"
echo "Compressed video saved as: $output_file"
}
ffmp4 foo.webm-> foo_sd.mp4
fftime() {
input_file="$1"
output_file="${input_file%.*}_cut.mp4"
ffmpeg -i "$input_file" -c copy -ss "$2" -to "$3" "$output_file"
echo "Cut video saved as: $output_file"
}
fftime foo.mp4 01:30 01:45-> foo_cut.mp4
Note, fftime copies the audio and video data without re-encoding, which can be a little janky, but often works fine, and can be much (100x) faster on large files. To re-encode just remove "-c copy"
https://github.com/atuinsh/atuin
Discussed 4 months ago:
Atuin – Magical Shell History https://news.ycombinator.com/item?id=44364186 - June 2025, 71 comments
So, you created a square wheel, instead of a NASA wheel.
That, plus knowing how to parse a man file to actually understand how to use a command (a skill that takes years to master) pretty much removes the need for most aliases and scripts.
Does this mean that you learned to code to earn a paycheck? I'm asking because I had written hundreds of scripts and Emacs Lisp functions to optimize my PC before I got my first job.
As an aside, I find most of these commands very long. I tend to use very short aliases, ideally 2 characters. I'm assuming the author uses tab most of the time, if the prefixes don't overlap beyond 3 characters it's not that bad, and maybe the history is more readable.
Even more useful is just learning the ICAO Spelling Alphabet (aka NATO Phonetic Alphabet, of which it is neither). It takes like an afternoon and is useful in many situations, even if the receiver does not know it.
https://gist.github.com/jgbrwn/7dd4b262c544f750cb0291161b2ec...
(actually avoids having to do a one liner like: for h in {1..5}; do dig +short A mail”${h}”.domain.com @1.1.1.1 )
Hmm speaking of which I need to add in support for using a specific DNS server
I set this stuff up so long ago I sort of forgot that I did it at all; it's like a standard feature. I have to remember I did it.
I use ctrl-R with a fuzzy matching program, and let my terminal remember it for me.
And before it's asked: yes that means I'd have more trouble working in a different/someone else's environment. But as it barely ever happens for me, it's hardly an important enough scenario to optimize for.
I tend to try to not get too used to custom "helper" scripts because I become incapacitated when working in other systems. Nevertheless, I really appreciate all these scripts if nothing else than to see what patterns other programmers pick up.
My only addition is a small `tplate` script that creates HTML, C, C++, Makefile, etc. "template" files to start a project. Kind of like a "wizard setup". e.g.
$ tplate c
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
}
And of course, three scripts `:q`, `:w` and `:wq` that get used surprisingly often: $ cat :q
#!/bin/bash
echo "you're not in vim"
:'<,'>s/^/> /
#!/usr/bin/env bash
# ~/bin/,dehex
echo "$1" | xxd -r -p
and #!/usr/bin/env bash
# ~/bin/,ht
highlight() {
# Foreground:
# 30:black, 31:red, 32:green, 33:yellow, 34:blue, 35:magenta, 36:cyan
# Background:
# 40:black, 41:red, 42:green, 43:yellow, 44:blue, 45:magenta, 46:cyan
escape=$(printf '\033')
sed "s,$2,${escape}[$1m&${escape}[0m,g"
}
if [[ $# == 1 ]]; then
highlight 31 $1
elif [[ $# == 2 ]]; then
highlight 31 $1 | highlight 32 $2
elif [[ $# == 3 ]]; then
highlight 31 $1 | highlight 32 $2 | highlight 35 $3
elif [[ $# == 4 ]]; then
highlight 31 $1 | highlight 32 $2 | highlight 35 $3 | highlight 36 $4
fi
I also use the comma-command pattern where I prefix my personal scripts with a `,` which allows me to cycle between them fast etc.One thing I have found that's worth it is periodically running an aggregation on one's history and purging old ones that I don't use.
I'd rather take the pain of writing scripts to automate this for multiple environments than suffer the death by a thousand cuts which are the defaults.
> vim [...] I select a region and then run :'<,'>!markdownquote
Just select the first column with ctrl-v, then "i> " then escape. That's 4 keys after the selection, instead of 20.
> u+ 2025 returns ñ, LATIN SMALL LETTER N WITH TILDE
`unicode` is widely available, has a good default search, and many options. BTW, I wonder why "2025" matched "ñ".
unicode ñ
U+00F1 LATIN SMALL LETTER N WITH TILDE
UTF-8: c3 b1 UTF-16BE: 00f1 Decimal: ñ Octal: \0361
> catbin foo is basically cat "$(which foo)"Since the author is using zsh, `cat =foo` is shorter and more powerful. It's also much less error-prone with long commands, since zsh can smartly complete after =.
I use it often, e.g. `file =firefox` or `vim =myscript.sh`.
https://meta.wikimedia.org/wiki/Cunningham%27s_Law
...aaand less directly (though referenced in the wikipedia article)...
1. even if it costs more time, it could also save more annoyance which could be a benefit
2. by publishing the scripts, anyone else who comes across them can use them and save time without the initial cost. similarly, making and sharing these can encourage others to share their own scripts, some of which the author could save time with
alias v='nvim'
alias vv='f=$(fzf --preview-window "right:50%" --preview "bat --color=always {1}"); test -n "$f" && v "$f"'
alias vvv='f=$(rg --line-number --no-heading . | fzf -d: -n 2.. --preview-window "right:50%:+{2}" --preview "bat --color=always --highlight-line {2} {1}"); test -n "$(echo "$f" | cut -d: -f1)" && v "+$(echo "$f" | cut -d: -f2)" "$(echo "$f" | cut -d: -f1)"'
I've found that pedantic conversations here seem to actually have a greater potential for me to learn something from them than other forums/social platforms. On other platforms, I see someone providing a pedantic response and I'll just keep moving on, but on HN, I get curious to not only see who wins the nerd fight, but also that I might learn at least one thing along the way. I like that it's had an effect on how I engage with comment sections.
# If this is an xterm set the title to the directory stack
case "$TERM" in
xterm*|rxvt*)
if [ -x ~/bin/shorten-ds.pl ]; then
PS1="\[\e]0;\$(dirs -v | ~/bin/shorten-ds.pl)\a\]$PS1"
else
PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1"
fi
;;
\*)
;;
esac
The script shorten_ds.pl takes e.g. 0 /var/log/apt
1 ~/Downloads
2 ~
and shortens it to: 0:apt 1:Downloads 2:~
#!/usr/bin/perl -w
use strict;
my @lines;
while (<>) {
chomp;
s%^ (\d+) %$1:%;
s%:.*/([^/]+)$%:$1%;
push @lines, $_
}
print join ' ', @lines;
That coupled with functions that take 'u 2' as shorthand for 'pushd +2' and
'o 2' for 'popd +2' make for easy manipulation of the directory stack: u() {
if [[ $1 =~ ^[0-9]+$ ]]; then
pushd "+$1"
else
pushd "$@"
fi
}
o() {
if [[ $1 =~ ^[0-9]+$ ]]; then
popd "+$1"
else
popd "$@" # lazy way to cause an error
fi
}
Mine is called "md" and it has "-p" on the mkdir. "mkdir -p $1 && cd $1"
If something is time sensitive it is worth spending a disproportionate amount of time to speed things up at some later time. For example if you’re debugging something live, in a live presentation, working on something with a tight deadline etc.
Also you don’t necessarily know how often you’ll do something anyways.
abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ