My Favorite One Liners
muhammadraza.me
muhammadraza.me
Why is this becoming a more common practice? There is nothing more annoying than a picture of a block of text that I can't copy, quote, or modify and send back to someone.
Oh, but there is: Videos of bug reports where a person first has to explain that they have found a bug, and they will try to reproduce it now, and if you're still watching after 3 minutes you might see the important 5 seconds of the video, that could have been expressed in a few well-written sentences!
People intuitively can ‘show’ you what’s wrong but most non-developers will have a hard time phrasing it.
“I press the button and nothing happens” is representative of written bug reports I’ve seen. What button? What’s supposed to happen? What page are you on? How can I reproduce this?
Almost all issues I’ve seen with a video I can reproduce. But I agree that they should be succinct.
As long as we retain those opening, over-amplified metal riffs. Jump scares are why I watch tech vids.
Oh yeah, totally, my experience has been that video bug reports are literally a thousand times better than text bug reports. I've worked in console game dev where we even required reproducer videos because they're so much better at showing the context of what happened. Often the text description was wrong and/or wildly incomplete and/or full of assumptions the user made about how things work or what's going on, and the video would demonstrate the issue and allow me to not have to engage in a lengthy back-and-forth conversation trying to understand the situation.
> “A picture is worth a thousand words” is an adage many would agree with.
I do too, but until now, I had never read that the other way around, that a picture might cost a thousand words. ;)
Sure, not everyone's comfortable with a computer, and they think they're clever with a solution. I still get annoyed when I get one of these videos.
Put in a ticket asking how to do something? They sent you a link to a very slow-moving screencast of going in and turning an option on/off or configuring a setting. No audio!
Their knowledge base articles were just a collection of links to screen recordings! It was so annoying.
Guess what happened when that company shut the free version of their app down...
If you do a minimum of testing, bugs often depend on context. For example, in case of a UI bug, maybe the user zoomed in, maybe he is using a non-default font, maybe he is using a different locale, maybe he did some action without realizing it (ex: scrolling, resizing the window), maybe the time is incorrect, etc...
"I click that button and it crashed" isn't going to help you there, you know it doesn't crash, you use that button all the time...
If it is as straightforward as it looks, watching that 3 minute video is your punishment for not testing. Yes, I know, I don't test either, but don't blame the reporter for it.
I like it so much that I've considered implementing always-on screen recording in our QA debug builds.
Just look at the amount of garbage "here's my code as a screenshot, what's wrong?" questions Stack Overflow has to remove each and every single day.
ps aux | convert label:@- process.png
And got an image that was useless. Nothing readable.While this command works fine and is readable too at 100% zoom, I wonder why one would do this. Isn't copy-pasting the text output of 'ps aux' more convenient than creating a large image out of it that is not easy to read, filter, etc.?
ps aux | pbmtext | pnmtopng > process.png
Don't forget search.
Too many StackOverflow posts start with a screenshot of yum errors or mysql logs.
Ugh.
For others it's pretty clear though: taking a smartphone picture and emailing it around is probably always faster than other means. Plus I'm pretty sure less tech-savy people simply have no idea Ctrl-C works nearly everywhere, including shells and dialog boxes.
So, sadly, the picture is made exactly with the purpose of proper quoting, unfortunately losing the textual content :(
And... that command doesn't work for me when I'm using ssh to access my servers or using x2go.
ps aux | nc termbin.com 9999sharing a snapshot is guaranteed to be easy to do in two clicks
sharing text is less so, selection is more work, finding a host is more work
"python3 -m http.server" is really useful when building simple JavaScript pages, or when you need a simple static file server for testing.
"ss -p" is great, but if you just want to see what's hogging your bandwidth, iftop and nethogs are much better.
My favourite one-liner is "open .", to open the current directory in Finder. The open command can also open URLs and other files.
I also have an alias for "osascript -e 'display notification "'"$1"'"'", which will display the text you choose in a MacOS notification. It's useful when you need to be notified at the end of a long-running task. "printf '\a'" is also useful if you need the terminal to "ding".
Speaking of Windows, "pushd \\servername\sharename" is a simple way to mount a share in Windows, if you have the login creds cached, and set the new drive letter as your active drive. Useful if you need to bounce around a bunch of shares.
It's not "start" is an alias to "explorer", it's that "start" runs the args through "ShellExecute".
I mention this only because it has some other uses. For instance, Windows apps can install run handlers so that something like Start->Run->Excel will launch Excel. Just running "excel" on a command prompt won't work, but "start excel" will work, since that kicks off the right path.
You can also use something like "start /w filename.txt" to start an instance of your editor, and wait for it to close (well, mostly, some apps do weird things and break this)
This one is great. Very, very useful.
https://github.com/jvinet/dotfiles/blob/master/bin/rin
Examples:
$ rin +30 Check the turkey
$ rin '14:30 tomorrow' Watch baseball
I currently have it setup so it pops up a modal dialog using Zenity. As well, it uses my cheap-and-cheerful bespoke notification doohickey that I have running in waybar, another script called notify: https://github.com/jvinet/dotfiles/blob/master/bin/notifyThis way, I have a nagging badge/icon in my waybar system tray until I finally do check that turkey and watch that baseball.
For linux one can use `xdg-open .` to use the associated application. Works with pdf, image files, videos, etc.
I have the alias x=xdg-open in my .bashrc, so that I use `x somefile` to open files.
noti() {
osascript -e \
'on run argv
display notification (item 1 of argv) with title "Notification"
end run' \
$1
}
# Example:
noti 'Hello world!'
This fixes any escaping issues by passing the notification string to osascript as an argument instead of embedding it in the text of the program (which makes things like quotation marks not work correctly).Sticking it in your .bashrc or .zshrc will make it available at any time in your shell.
explorer.exe $(wslpath -w "$PWD")
It's a bit lengthy so this is always aliased in my .bashrc when using WSL alias open="/mnt/c/Windows/explorer.exe"
Edit: Added formattingCan also combine with a vocal message: sleep 2; osascript -e 'say "Hello World!"'; osascript -e 'display alert "hello world"'
The last one copied from https://code-maven.com/display-notification-from-the-mac-com...
> If you want to cat bunch of files at once you can this command.
> rm -f !(test.txt).
I hope whoever follows this blindly doesn’t lose too many files they wanted to cat.
./very-long-task.sh && say 'success' || say 'fail'
I use it when I need to context switch and leave something running. `espeak` is an alternative for `say` on Linuxes. #!/bin/bash
$@ && say 'The command finished.' || say 'Danger! Something blew up!'
To give me a quick way to run commands and hopefully enough words to catch my attention."A && B || C is not if-then-else. C may run when A is true":
The problem is that "In this case, if A is true but B is false, C will run."
I guess with B as "say", B will never be false, but generally it's really not the same as if-then-else.
# Generate a random password and copy it to the clipboard.
pw () {
pwgen -sync "${1:-48}" -1 | xclip
}
# Get the current weather.
weather () {
curl https://wttr.in/"${1}"
}
# Get the numeric value of a file / directory's permissions.
alias octal="stat -c '%a %n'"
All of my aliases are listed in my dotfiles at: https://github.com/nickjj/dotfiles/blob/master/.aliases function genpasswd() {
openssl rand 150 | LC_CTYPE=C tr -dc '[[:alnum:]!@#$%^&]' | tr -d iIlLOo0 | cut -c 1-${1:-12};
}I made a whole video on generating random password from the command line and compared a few options (including using openssl) at: https://nickjanetakis.com/blog/generate-a-random-secure-pass...
The TL;DR for not using openssl is that you're not going to get the same amount of characters every time. For example if you run yours with 48 characters instead of 12 it won't generate 48 characters every time you run it. With pwgen (something you can apt or brew install) you know what you're getting every time.
Did you test your solution on macOS btw? I know macOS uses an ancient version of Bash and has different binaries that act differently vs Linux (such as sed). I don't have a Mac here but I do try to make my dotfiles compatible with it. If your solution works on macOS it would be nice to drop the pwgen dependency.
git log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold cyan)%aD%C(reset) %C(bold green)(%ar)%C(reset)%C(bold yellow)%d%C(reset)%n'' %C(white)%s%C(reset) %C(dim white)- %an%C(reset)' --all
Add a global alias: git config --global alias.lg "log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold cyan)%aD%C(reset) %C(bold green)(%ar)%C(reset)%C(bold yellow)%d%C(reset)%n'' %C(white)%s%C(reset) %C(dim white)- %an%C(reset)' --all"
Usage: git lgGoogle/DDG search for "git lg2" should also reliably take you to this SO answer to copy the alias from: https://stackoverflow.com/a/9074343
git branches
Code for your ~/.gitconfig branches = branch -a --sort=-committerdate --format='\
%(HEAD) \
%(if)%(HEAD)%(then)\
%(color:"#329664")%(objectname:short)%(color:reset) \
%(color:"#222222")[%(committerdate:short)]%(color:reset) \
%(color:green)%(refname:short)%(color:reset) \
%(else)\
%(if)%(upstream)%(then)\
%(color:"#999999")%(objectname:short)%(color:reset) \
%(color:"#222222")[%(committerdate:short)]%(color:reset) \
%(refname:short) \
%(color:"#ffc662")%(upstream:track)%(color:reset) \
%(else)\
%(color:"#963232")%(objectname:short)%(color:reset) \
%(color:"#222222")[%(committerdate:short)]%(color:reset) \
%(color:red)%(refname:lstrip=1)%(color:reset)\
%(color:"#ffc662")%(upstream:track)%(color:reset) \
%(end)\
%(end)\
'
Meaning HASH Commit_date Branch_Name
A white branch_name means it is local.
Red means it is remote.
Yellow branch_name is the current branch.
It will also tell you if your checked out branch is ahead or behind the remote branch. $ cargo build --release
error: failed to get `bitflags` as a dependency of package `alacritty v0.9.0-dev (/home/myuser/sources/alacritty/alacritty)`
Caused by:
failed to initialize index git repository
Caused by:
failed to parse config file: invalid configuration key (in /home/myuser/.config/git/config:57); class=Config (7) $ ls | pbcopy
$ pbpaste > out.txt
You can also put this in a function in order to get the path of the frontmost Finder window: osascript 2>/dev/null -e '
tell application "Finder"
return POSIX path of (target of window 1 as alias)
end tell'
Get the current Finder selection: osascript 2>/dev/null -e '
set output to ""
tell application "Finder" to set the_selection to selection
set item_count to count the_selection
repeat with item_index from 1 to count the_selection
if item_index is less than item_count then set the_delimiter to "\n"
if item_index is item_count then set the_delimiter to ""
set output to output & ((item item_index of the_selection as alias)\'s POSIX path) & the_delimiter
end repeat' pbpaste | json_pp | pbcopy ps auxw | pbcopy # After alias works on WSL too.For instance, format the JSON in your clipboard: pbpaste | jq .
pbpaste | python3 -m json.tool
hotkey: "du-m"
Use: Sort directories by usage:
du -m --max-depth=1 | sort -n
hotkey: "wpinfo"
Use: gets basic WordPress site info:
code for AHK
::wpinfo::
(
echo Home URL $(wp option get home) ; echo Site URL $(wp option get siteurl);echo "###
Plugins ###"; wp plugin list;echo "### Themes ###"; wp theme list;echo "### Users ###";
wp user list; echo "### Roles ###"; wp role list; wp core verify-checksums
)
hotkey: awk(1-5)use: saves me typing something I fat finger every. single. time.
awk '{ print $1 }'
awk '{ print $2 }'
awk '{ print $3 }' etc
AHK:
::awk1::awk '{{} print $1 {}}'
There are others but these are the ones that come to mind. The main thing isn't the scripts but the automation. And AHK can save a ton of error-prone typing or copy/pasting in these scenarios.The same thing in bash would be:
$ arg1 () { echo $1; }
$ arg1 one two three
one
Splitting fields is easy with cut: $ echo one two three | cut -f 1 -d " "
one
Normally you just want to stuff it into a variable in which case read is much easier: $ read arg1 arg2 arg3 < <(echo one two three)
$ echo arg1
one
Symbolic names are normally much easier to read than numeric positions.That last example looks a bit weird with <() instead of a pipe, but that's just because the right hand side of a pipe is a separate shell so setting variables in it is a bit useless. It's nothing specific to read.
However, instead of:
git log --format='%aN' | sort -u
I'd recommend using git shortlog, as it'll provide you with counts. git shortlog -snGreat feature though, it adds a ton of extra pattern matching. Not (!) is definitely my most used though.
$ bash -c 'shopt -s extglob; rm -- !(x)'
bash: -c: line 1: syntax error near unexpected token `('
bash: -c: line 1: `shopt -s extglob; rm -- !(x)'
Because of the strangeness of the bash parser, the glob has to come on the preceding line: $ bash -c $'shopt -s extglob\nrm -- !(x)'> If you want to cat bunch of files at once you can this command
You can use cat itself for this (and save typing a few characters):
cat *It makes no sense. Starting your pipe with cat is alright. I make a point of always starting all my pipes with cat, even in the cases where it is a bit unnatural.
For those who may not know, you can put the I/O redirection anywhere in the command, not just at the end.
So you can write
< input_file.txt grep some_pattern | grep another
Which has the same effect as grep some_pattern < input_file.txt | grep another
but puts the input redirection at the beginning so you can easily follow the data flow from left to right.I use "redirection first" in other cases such as
1>&2 echo "Error: missing file"
To make it clear up-front that I'm writing to stderr.
cat file |\
program1 |\
program2 |\
...
If you use a redirection, since the command does not start with a pipe the symmetry is broken.Redirections at the start of the line are fun. I have an alias
alias null='>/dev/null 2>/dev/null'
this allows to run GUI programs without cluttering the terminal with useless GTK/QT warnings: null evince file.pdfEdit:
cat file |
program1 |
program2 |
... echo foo | # echoing foo
tr 'a-z' 'A-Z'
FOOI typically start with (say) `head file | grep '2020'`. Once it does what I want I move to the next step, and so on until it's done. At that point, and having chained 5-6 commands, replacing `head` with `cat` is faster and less likely to break due to me putting the '<' in the wrong place. The simplicity and extra peace of mind is well worth an extra process IMHO.
It's a good thing to be aware of the differences when needed, but often the execution speed is not the reason for writing a bash script.
cat file.txt | somemonstrousoneliner
immediately tells me it's reading file.txt and doing something with the contents.
Burying the filename deeper in the string makes it harder to figure that out.
grep ^ *
would fix that and is just as short.I believe this command is present to prefix each line of output with the filename. But this ignores all the blank lines. That can of course be fixed easily with:
grep ^ *
Here is what I normally use myself if I want to show the content of files with their filenames: tail -n +1 *
This shows the name of the file once at the beginning of each file and no more. Here is an example: $ tail -n +1 *
==> bar.txt <==
bar 1
bar 2
bar 3
==> baz.txt <==
baz 1
baz 2
baz 3
==> foo.txt <==
foo 1
foo 2
foo 3 tail -n +1 `find * -maxdepth 0 -type f`
Getting long enough to make an alias...> This command will allow you to share your terminal session in real time.
Using `script` for this seems nice for when you don't want them to be able to control the same computer. Like person foo on their computer would
nc -l 9000
then you could script -f >(nc foo 9000)
to show them your session. One could also add some encryption to the pipe.If both controlling the same computer is not a problem or is even desired, then it's probably simplest to just share a tmux session. One runs `tmux` and the other `tmux a`.
At least for vim and htop, having a larger terminal window doesn't seem to be a problem as far as I can see.
Here's how to do this with screen instead of tmux.
Terminal 1:
screen -mS hello # create screen named "hello"
Terminal 2: screen -x hello # attach to shared screenTerminal 1:
screen
Terminal 2: screen -x
seems to be enough, too.I always use named screens since it's quicker and more organized than typing `screen -ls` before every time and then making a decision on whether or not to name the new one (I still think it's better to name the first one in any case in the vast majority of (my) cases).
awk '{print $1}' < apache.log | sort -n | uniq -c | sort -rn |less
Produces output like: 4482 66.249.73.135
3264 46.105.14.53
3157 130.237.218.86
2073 75.97.9.59
1013 50.16.19.13
...
And fairly easy to throw in a "grep" for specific fetched urls, slices of time, etc.Some of the records you may have to search could have the port attached (i.e. output of netstat, haproxy logs or others) so for stripping them I add
rev | cut -d ":" -f 2- | rev
on the list of IPs to not get messed up with IPv6 records.
Yes but I don't understand the advantage of that instead of simply using :
cat *.*
or if you want to display the filenames :
tail *
works fine too. Maybe someone can explain.
# Use jq to craft json documents
jq -en --rawfile key some_id_rsa \
'{ "ssh_private_key": $key, "hosts": [
{ "type": "EC2", "name": "backenddev", "id": "i-0123456789", "address": "1.2.3.4", "region": "us-west-1" }
] }' > metadata.json
# Use jq to import Terraform resources from a state file
jq -er '.modules[].resources | to_entries | .[] | [ "terraform", "import", .key, .value.primary.id ] | @sh' \
generated/aws/route53/terraform.tfstate \
| xargs -L1 env
# Use Bash to check for a TCP connection (like 'nc -z')
timeout 1 bash -c 'cat < /dev/null > /dev/tcp/127.0.0.1/3306'A one liner to update all your npm deps to latest. I use this quite a lot.
basho --import './package.json' pack -j pack -j 'Object.keys(x.dependencies)' -m x -e 'npm install ${x}@latest'
Explanation of how this works:1) Import package.json, call it 'pack'. 2) Put pack in the pipeline. 3) map pack to pack.dependencies. 4) flatMap (-m x) to remove nesting. Because pipeline is an array, and it contains pack.dependencies - another array. 5) Exec command with '-e'
atopsar -p | tail -n +7 | grep '\S' | awk '{printf("\n%s %6.2f ",$1, $5); for (i = 0; i<$5; i++) {printf("")}}'; echo
sample: https://gist.github.com/defulmere/bec1aef40ca4cddb5c421ffa5f... atopsar -p | grep ":[0-9]\{2\}\s\+[0-9]" | awk '{printf("\n%s %6.2f ",$1, $5); for (i = 0; i<$5; i++) {printf("*")}}'; echo !seen[$0]++
which gives the union of the lines of all the input files, with none of that 'sort | uniq' business.It's not a one-liner, but here's intersection:
! buf[$0]++ { acc[$0]++ }
ENDFILE {
delete buf;
files++
}
END {
for (k in acc) if (acc[k] == files) print k
}
and here's set difference: ! filenum { acc[$0] = 1 }
filenum { delete acc[$0] }
ENDFILE { filenum++ }
END {
for (k in acc) print k
}
I keep these in my ~/bin with evocative names (e.g., 'union' and 'set-diff'). Once I did that, lots of other things became one liners.Screen has a multi-display mode you can use with "screen -x" that lets multiple clients connect to the same session. Useful if you want to walk someone through a process.
1: gotta light?
No match.
Quickly followed by:
2: Could you beat up superman?
No match.
Oh, the days when csh was cool and not retro.
$ bill gates
Did you mean “kill gates”?
$ %blow
No such job
We had fun times.It would handle most known commands and maybe had plugin support for the rest.
Just a thought I had. Don't really know if it's possible or feasible. But it would make working with command line much more predictable and easier especially if it also supported jmespath! What do you guys think?
“Like sed for JSON data”
The output would then be appropriate for jq.
(I don't have an opinion yet. Been meaning to try it for a year now but a shell is a difficult thing to switch)
Interestingly enough, the Arista CLI actually implements something like this, but it's not a real pipe or a separate command - each command implements it's own `<command> | json` handler.
bin/rspec $(find spec -type f -exec stat -f '%a %N' {} \; | sort -r | head -1 | awk '{print $NF}')
So if you are working on a spec & save it, running this will execute that spec & only that spec. I have it hooked up to a mapping in neovim, so hitting `<leader>rt` runs the test.Needs some tweaking, and I'm aware that guard exists. This is simpler. Quick & does the job.
Count processes and threads by user on Linux:
# ps -Teo euser=,comm= | sort | uniq -c | sort -nr
zgrep -Po '^[0-9.]+' /var/log/apache2/test.access.log | sort | uniq -c | sort -n dig TXT -4 +short o-o.myaddr.l.google.com @ns1.google.comAlso, I can find the resolver IP for popular public resolvers this way too.
This is probably the coolest thing I will learn about today.
Copy a selected rectangle of the screen into clipboard
google-chrome --headless --disable-gpu --print-to-pdf=out.pdf https://www.cnn.com
pdftotext -layout -nopgbrk out.pdf - | less> grep . *
you can "cat *"
> ps aux | convert label:@- process.png
copy-pastable text is a better way to exchange text.
> mkfifo hello; script -f hello
you forget to mention that the other side needs to cat this file. but also, tmux might be better for this.
> > grep . *
> you can "cat *"
The advantage of `grep . *` is that it omits empty lines and includes the source file on each matching line by default. function fvi { grep -rl $1 . | xargs zsh -c 'code "$@" <$0' /dev/tty } svn diff "$@" | colordiff | less -R -x4You're welcome.