Skip to content

Instantly share code, notes, and snippets.

@Chengings
Last active July 25, 2025 16:46
Show Gist options
  • Save Chengings/48e18165244e03a6eb0c3cdaadaf82b7 to your computer and use it in GitHub Desktop.
Save Chengings/48e18165244e03a6eb0c3cdaadaf82b7 to your computer and use it in GitHub Desktop.
Cheatsheets
trim_trailing_whitespace = true
########
# curl #
########
curl --compressed # Request compressed response
curl -H "User-Agent:" https://goo.gl # --header Pass custom header(s) to server.
# Delete an internally generated header by removing value after colon (:)
curl -v https://captive.apple.com # −−verbose
# ’>’ means "header data" sent by curl
# ’<’ means "header data" received by curl
curl -i https://captive.apple.com # --include Include protocol response headers in the output
curl -I https://captive.apple.com # --head Fetch headers only
curl -s https://captive.apple.com http://neverssl.com # --silent Quiet mode with multiple urls
curl -L https://en.wikipedia.org/wiki/Special:Random # --location Follow redirects
curl -w "%{url_effective}\n" -I -L -s -o /dev/null https://apple.co.uk # print final follow url
curl -O "https://via.placeholder.com/[50-75:5].{png,gif,jpg}" # −−remote-name Write output to a file named as the remOte file
# Numerical range start from 50 to 75 with an increment of 5
# And a list of png, gif and jpg
# 50.gif 50.jpg 50.png ... 75.gif 75.jpg 75.png
curl -R "https://www.iana.org/_img/bookmark_icon.ico" # --remote-time Set the remote file's time on the local output.
curl -ROJ "https://www.iana.org/_img/bookmark_icon.ico" # --remote-header-name Use the Content-Disposition filename.
# Combined with RO options to save file with server's Last-Modified and filename.
curl "https://via.placeholder.com/[50-75:5].png" -o "placeholder_#1.png" # --output Write output to <file>
# Each "glob" used in a URL gets a separate variable.
# They are referenced as '#[num]'. Start with 1
# placeholder_50.png placeholder_55.png placeholder_60.png placeholder_65.png placeholder_70.png placeholder_75.png
curl -o /tmp/apple.html https://captive.apple.com -o /tmp/neverssl.html http://neverssl.com # Write multiple output files
curl -fsSL https://deno.land/x/install/install.sh # Multiple short options. -f Fail silently. -S Show error even when -s is used
xargs curl --remote-name-all <urls.list.txt # Download whole URLs at once and save file by its remote name. Serial manner by default.
xargs curl -Z --remote-name-all <urls.list.txt # --parallel Perform transfers in parallel. Default is 50 transfers. Curl >= 7.66 (Sep 2019)
xargs -P0 -n1 curl -O <urls.list.txt # Alternatively, download one URL per time but use many processes (-P 0) simultaneously.
curl -h # --help Get a list of the most important and frequently used options.
curl -h http # HTTP and HTTPS protocol options
curl -h verbose # Options related to any kind of command line output of curl
curl -h category # Get more options listed for that specific area.
curl -h all
########
# wget #
########
wget -r --no-parent # Download whole site without parent (r)ecursively
wget -i urls.txt # Read URLs from a local or external f(i)le
##############
# References #
##############
cat <<EOF
https://everything.curl.dev/
https://everything.curl.dev/usingcurl/verbose/writeout
https://curl.github.io/curl-cheat-sheet/http-sheet.html
https://antonz.org/interactive-api-tutorials/
https://www.gnu.org/software/wget/manual/wget.html
EOF
date -u # Use UTC0
date '+<format>'
date '+%s' # Unix Epoch time. Compatiable with BSD & GNU
date '+%Y-%m-%d'
# > 2199-12-31
date '+%T' # 24-hour clock time [00,23]; same as %H:%M:%S
# > 22:25:59
date '+%r'
# > 10:25:59 pm
date '+%c' # Locale's date and time
# > Thu 19 Aug 22:30:53 2021
date '+%V' # ISO week number of the yar [01,53]
# > 33
###############
# Adjust time #
###############
## BSD
date -v -57M
date -v -3H
date -v -1d
date -v -3d
date -v +1d
date -v +3m
date -v +6m -v +15d
## GNU
date -d '-57 minutes'
date -d '-3 hours'
date -d 'yesterday'
date -d '-3 days'
date -d 'tomorrow'
date -d '+3 months'
date -d '+6 months 15 days'
##################
# Timezone & DST #
##################
zdump -v GB | grep "$(date '+%Y')" # Display GB timezone and begin/end of dst. Equivalent to https://www.gov.uk/when-do-the-clocks-change
##############
# References #
##############
cat <<EOF
POSIX date: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/date.html
GNU (coreutiles) date: https://www.gnu.org/software/coreutils/manual/html_node/date-invocation.html
Example of GNU date: https://www.gnu.org/software/coreutils/manual/html_node/Examples-of-date.html
EOF

Docker

Pull

docker pull <image>:<tag>
docker pull redis:6.2-alpine
docker pull busybox:stable

Run

# At least specific --name and image:version
docker run --name <container_name> --env <VAR=val> --detach <IMAGE:latest>

# Allocate a pseudo-(t)TY connected to the container’s std(i)n
docker run -it <image>

# Automatically remove the container when it exits
docker run --rm <image>
docker run -it \
	--rm busybox:stable

# Print default nginx.conf and conf.d/default.con
docker run --rm 'nginx:1.21-alpine' cat /etc/nginx/nginx.conf
docker run --rm 'nginx:1.21-alpine' cat /etc/nginx/conf.d/default.conf

docker run \
	-p 6379:6379 \
	--detach \
	--env REDIS_REPLICATION_MODE=master \
	--name redis \
	--restart unless-stopped \
    redis:6.2-alpine 'redis-server'	# Start redis 6.2 and ex(p)ose port 6379 to host, then run 'redis-server' command.
  					# It will pull docker image automatically.

Execute a command in a running container

A better approach would be:

  1. Skip -t by default for automated tasks and scripts. The TTY allocation might interfere with output redirection
  2. Use -t only when you specifically need formatted output
  3. Use both -it when you need interaction
# It explicitly uses the shell to interpret the command
# For a quoted command, it MUST use 'sh -c' or 'bash -c'
docker exec <container> /bin/sh -c "mkdir /tmp/$(date +'%s')"
docker exec <container> mkdir /tmp/"$(date +'%s')"

# Import db.sql into new_db database in Docker container 'db-container' as root user.
# Option -i is required for file input as it keeps STDIN open to receirve the input file.
docker exec -i db-container /usr/bin/mysql -uroot new_db </var/tmp/db.sql

# `-i`: Keeps STDIN open (interactive mode)
# `-t`: Allocates a pseudo-TTY (terminal)

# Using vim (with -it)
# Without `-it`, this will not work properly
docker exec -it <container> vim /app/config.json

Container

docker container inspect <container_image|id>
docker container prune

Volume

docker volume create <volume_name>

# Remove all unused local volumes
docker volume prune

Image

docker image prune

# Remove all images which are not used by existing containers.
docker image prune -a

# Show all top level images, their repository and tags, and their size.
docker images

# Show ALL including intermediate images
docker images -a

# Search images by name
docker images php

# Search images by name and tag
docker images php:8

# Filter (-f) only dangling images, show only images id (-q) and remove those images via `docker rmi` command.
docker rmi $(docker images -f "dangling=true" -q)

Network

docker network prune

System

# Prune EVERYTHING, except volumes (> Docker 17.06.1)
docker system prune

# All volumes not used by at least one container
docker system prune --volumes

Compose

docker compose up
docker compose up -d
docker compose down
docker compose build

See also

exiftool

https://exiftool.org/exiftool_pod.html

Options

-<TAG>      # get tag data
-'*gps*'    # get all gps related tags
-time:all   # get all date/times
--<TAG>     # exclude/hide tag data

-a          # allow all duplicate tags to be shown
-e <extennsion> # process only a specificified ext
--e <extension> # process WITHOUT a specified ext
-g          # format output by tag group
-G          # similar to the -g, but show the group name for each tag
-json
-list       # list various exiftool capabilities
-listf      # list supported format
-listgeo    # list geolocation database
-listr      # list all recognised format
-listw      # list writeable tags
-listw -XMP:All # list all writable XMP tags
-listwf     # list writable format
-n          # convert to machine-readable value
-short      # -s: short output
-s2         # -s -s: no extra spaces
-s3         # -s -s -s: print values only (no tag names)
-sort
-w <extension>  # -textOut: write console output to a file

Examples

Write output as a file

# Write file name and file type output as a text file with the same name as the input file
exiftool -w txt -FileName -FileType <file>

Get short output

exiftool -s1 -make Red-browed_Finch_-_Penrith.jpg
Make                            : Canon

exiftool -s2 -make Red-browed_Finch_-_Penrith.jpg
Make: Canon

exiftool -s3 -make Red-browed_Finch_-_Penrith.jpg
Canon

Get camera model in tabular format

exiftool -T -make -model <file>      # Get camera model data in tabular format

Get data by tag group

exiftool -g Red-browed_Finch_-_Penrith.jpg
---- File ----
File Name                       : Red-browed_Finch_-_Penrith.jpg
---- EXIF ----
Make                            : Canon
---- ICC_Profile ----
Profile Version                 : 2.0.0
---- Composite ----
Aperture                        : 6.3

exiftool -G Red-browed_Finch_-_Penrith.jpg
[File]          File Name                       : Red-browed_Finch_-_Penrith.jpg
[EXIF]          Make                            : Canon
[ICC_Profile]   Profile Version                 : 2.0.0
[Composite]     Aperture                        : 6.3

# show all tags under specifig group
exiftool -G '-COMPOSITE:*'
exiftool -G '-EXIF:all'

# show all duplicate tags ⭐
exiftool -a -G -GPSAltitude Red-browed_Finch_-_Penrith.jpg
[EXIF]          GPS Altitude                    : 13.89999963 m
[Composite]     GPS Altitude                    : 13.8 m Above Sea Level

exiftool -G -EXIF:GPSAltitude Red-browed_Finch_-_Penrith.jpg
[EXIF]          GPS Altitude                    : 13.89999963 m

exiftool -G -COMPOSITE:GPSAltitude Red-browed_Finch_-_Penrith.jpg
[Composite]     GPS Altitude                    : 13.8 m Above Sea Level

Process all files (files with specific extension) in the specified directory <dir>

exiftool -ext jpg <dir>

exiftool -ext heic '-GPSDateTime>FileModifyDate' '-GPSDateTime>FileCreateDate' <dir>

Print the GPS date and time information from the specified image

exiftool -printFormat 'This image was taken at $gpsdatetime' image.jpg

Recursively get the GPS data from all image files located in the ~/Pictures

# GPS tags
exiftool -r "-*gps*" ~/Pictures

# Only date and time
exiftool -r -gpsdatetime ~/Pictures

Print gps data with machine-readable format

# GPSLatitude and GPSLongitude will be displayed in decimal format ⭐
exiftool -n "-*gps*" <files>

Adjusts both the file's modification date and creation date to match the original date and time the photo was taken

exiftool "-DateTimeOriginal>FileModifyDate" "-DateTimeOriginal>FileCreateDate" <files>

Update DateTimeOriginal, CreateDate and ModifyDate. The AllDates tag is provided as a shortcut for these three tags, allowing them to be accessed via a single tag. ⭐

# With timezone offset. In this case, set time zone to Bangkok
exiftool -AllDates='2024:05:05 17:13:00' -OffsetTime'*=+07:00' <file>

Update all time tags from DateTimeOriginal and also update file creation and modification timestamps.

# 'wm w' is a must. https://exiftool.org/forum/index.php?topic=9796.msg50909#msg50909
exiftool -'DateTimeOriginal>time:all' -'DateTimeOriginal>FileCreateDate' -'DateTimeOriginal>FileModifyDate' -wm w <file>

Add GPS coordinates What format do I use for writing GPS coordinates?

# -ver 12.36 and later ⭐
exiftool -gpsposition="42 30 0.00 S, 33 15 0.00 W" <file>
exiftool -gpsposition="-42.5, -33.25" <file>

# -ver 12.44 and later
exiftool -composite:gpslatitude="42 30 0.00 S" -composite:gpslongitude="33 15 0.00 W" <file>
exiftool -composite:gpslatitude="-42.5" -composite:gpslongitude="-33.25" <file>

# For video, use 'Keys', it should work with Apple software. Google Photos doesn't support more than 5 decimal places.
exiftool -Keys:GPSCoordinates="33.7312, -84.3734, 30" <video>

Manipulate XMP's geolocation data ExifTool Geolocation Feature

# LOOK UP (no mofification) gelocation data from GPS position (preferably), or from city, state/province and country information.
exiftool -api geolocation "-geolocation*" <file>
exiftool -api geolocation="13.69152, 100.75089"
exiftool -api geolocation="Manchester,England"

# COPY GPS position metadata to an XMP and IPTC sidecar file with the tag `xmp:geolocate`
exiftool '-gpsposition>xmp:iptc:geolocate' <file>

# Set XMP:GPSLatitude, etc and IPTC:City, etc for Bangkok, Thailand
exiftool -xmp:iptc:geolocate="bangkok,th" <file>

# Set ⭐
# - GPS:GPSLatitude*, GPS:GPSLongitude* and altitude (in metre unit)
# - XMP:City, XMP:State, XMP:CountryCode, XMP:Country
exiftool -gpsposition="-42.5, -33.25" -geolocate="-42.5, -33.25" '-GPSAltitude*=35' <file>

Remove all gps data

# Use -a to ensure the removal of duplicate tags in different groups ⭐
exiftool -a -'*gps*'= <file>

Remove specific metadata groups

# Remove EXIF and IPTC, but it might retain XMP data
exiftool -exif:all= -iptc:all= <file>

# Remove only the GPS latitude and keywords tags
exiftool -exif:GPSLatitude= -iptc:Keywords=

Remove all metadata such as EXIF, IPTC, XMP

exiftool -all= filename.jpg

# but keep exif's createdate
exiftool -all= -tagsfromfile @ -exif:createdate

Filtering with conditional logic

# List the filenames of image files taken with Canon cameras in the current working directory and its subdirectories recursively
exiftool -if '$Make eq "Canon"' -r "$(pwd)" \
-filename -model

# If the "Make" tag exists in a file's metadata, it will be processed
exiftool -if '$Make' -r "$(pwd)" \
-filename -make -model

# Use regex to search Sony cameras with case-insensitive condition
exiftool -if '$Make =~ /sony/i' -r "$(pwd)" \
-filename -make -model

See also

eza -sold # sort old files at bottom of list
eza -snew # sort new files at bottom of list
eza --total-size # show directory size
fd -0 <pattern> | xargs -0 rm -f # search and delete files, support file with space
fd -e png -x sips -s format jpeg {} --out {.}.jpg # convert png to jpg. Required `sips`
fd -e avi -x ffmpeg -i {} {.}.mp4 # convert avi to mp4 with default mode. Required `ffmpeg`
# Search hidden and ignore file
fd --hidden
fd -H
fd --no-ignore # disable .gitignore bahaviour
fd -I
fd -HI # equivalent to `fd --hidden --no-ignore`
fd -HI '^\.' # list all hidden files and directories
# Filtering by file modification time
# duration uses human time: sec, min, hr, d, w, M, months, y. For instance, 2w or 1d.
# date uses "2018-10-27 10:00:00"
fd --changed-within <date|duration> <pattern>
fd --changed-before <date|duration> <pattern>
##############
# References #
##############
cat <<EOF
https://github.com/sharkdp/fd
https://docs.rs/humantime/1.1.1/humantime/fn.parse_duration.html
EOF

Download M3U8 or HLS

ffmpeg -protocol_whitelist file,http,https,tcp,tls -allowed_extensions ALL -i <file/http/protocols> \
-bsf:a aac_adtstoasc -c copy \
<output.mp4>
# "aac_adtstoasc" to convert Audio Data Transport Stream (ADTS) to MPEG-4 Audio Specific Configuration (ASC)
# normal mp4 container doesn't suppport the ADTS, only the ASC

Check Bitstream Filters Documentation and Supported Protocols.

Adding subtitle

# srt file
ffmpeg -i <file.mkv> -i <sub.srt> \
-c copy \
-bsf:a aac_adtstoasc \
file_w_sub.mkv

# iso mp4 format supports .vtt subtile
# language code 639-2 or 639-3 should be ok https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
ffmpeg -i <file> -i <eng.vtt> \
-c copy \
-c:s mov_text \
-metadata:s:s:0 language=eng \
<output>
# multiple languages
ffmpeg -i <file> -i <eng.vtt> -i <tha.vtt> \
-map 0 -map 1:s -map 2:s \
-c copy -c:s mov_text -c:s mov_text c:s mov_text \
-metadata:s:s:0 language=eng \
-metadata:s:s:1 language=tha \
<output>

x265 HEVC

# Convert to x265 with same audio codec (QuickTime playable).
# preset: ultrafast, superfast, veryfast, faster, fast, medium(default), slow, slower, veryslow and placebo
ffmpeg -i <file> \
-c:a copy \
-c:v libx265 \
-preset <preset> \
-tag:v hvc1 \
<output>

# macOS's videotoolbox api
# Normally it should have 'h264_videotoolbox' and 'hevc_videotoolbox' for newer mac & ffmpeg
ffmpeg -codecs | grep videotoolbox
ffmpeg -encoders | grep videotoolbox
# get hevc encoder options
ffmpeg -hide_banner -h encoder=hevc_videotoolbox

# To use videotoolbox, bitrate must be specific, can't use preset.
ffmpeg -i <file> \
-c:a copy \
-c:v hevc_videotoolbox \
-b:v <video_bitrate> \
-tag:v hvc1 \
<output>

Batch

# Convert avi videos to mp4
for i in *.avi; do ffmpeg -i "$i" "${i%.*}.mp4"; done

# Batch with parallel, must install fd. https://github.com/sharkdp/fd#parallel-command-execution
fd -e avi -x ffmpeg -i {} {.}.mp4

# Create 10-second video files. Start at 00:01:00 with overwrite (-y)
for bitrate in 500k 1000k 1500k 2500k 3000k 3500k;do
   ffmpeg -i <input_file> -c:v h264_videotoolbox -c:a copy -y -b:v $bitrate -ss 00:01:00 -t 00:00:10 output_$bitrate.<ext>;
done

# Loop a video 7 times. Check Concatenate: demuxer for more info
ffmpeg -f concat -safe 0 -i <(for i in {1..7}; do printf "file '%s'\n" <file>; done) -c copy <output>

Audio

# Convert input to aac format with constant bit rate
ffmpeg -i <file> -c:a aac -b:a 64k <output>.m4a

# Convert input to aac format, -vn means no video
ffmpeg -i <file> -vn -c:a aac <output>.m4a

# Convert input to muted vdo, -an means no audio
ffmpeg -i <file> -c:v copy -an <output>

# Relocate the moov atom to the beginning of the file
ffmpeg -i <input>.m4a -c:a copy -movflags +faststart <output>.m4a

Image

Extract every frames to jpg. The 5-second video with a frame rate 60 fps, it will extract 300 images.

ffmpeg -i <file> frame%06d.jpg  # frame000001.jpg and so on.

Change frame rate with -r option

ffmpeg -i <file> -r 10 frame%06d.jpg  # From above example, it will extract 50 (5s x 10fps) images.
ffmpeg -i <file> -r 1/10 frame%06d.jpg  # It will extract one image every 10 seconds.

Extract at a given time.

ffmpeg -ss 5 -to 8 -i <file> frame%06d.jpg  # extract frames between 5 and 8 seconds

Speeding up/slowing down

# Double video speed without audio
ffmpeg -i <file> -filter:v "setpts=0.5*PTS" -an <output>
# Double audio speed without video
ffmpeg -i <file> -filter:a "atempo=2.0" -vn <output>
# Double video and audio speed
ffmpeg -i <file> -filter:v "setpts=0.5*PTS" -filter:a "atempo=2.0" <output>
ffmpeg -i <file> -filter_complex "[0:v]setpts=0.5*PTS[v];[0:a]atempo=2.0[a]" -map "[v]" -map "[a]" <output>
# Slow down video
ffmpeg -i <file> -filter:v "setpts=2.0*PTS" <output>
# Slow down audio without video
ffmpeg -i <file> -filter:a "atempo=0.5" -vn <output>

Filter

tpad (Temporarily pad video frames)

# Add 1 second of black (default) screen at the beginning of video
ffmpeg -i <file> -filter_complex "tpad=start_duration=1" <output>

ffplay / ffprobe

fd --type=f -0 --max-depth=1 --max-results 25 \
| sort --random-sort -z \
| xargs -n1 -0 -t \
ffplay -vn -af "atempo=0.8" -autoexit -nodisp -loglevel 'quiet'
# Play audio only via ffplay. Limited to 25 files with random order and playback speed at 0.8x
# Apply -0 and -z options to eliminate issue caused by space (' ') in file name.

# Get video bitrate from mp4. Tried webm but doesn't work
ffprobe -v error -select_streams v:0 -show_entries stream=bit_rate \
  -of default=noprint_wrappers=1:nokey=1 <file.mp4>
# As a shell variable `vdo_bitrate="$(<above command>)"`

References

fzf: a command-line fuzzy finder

https://github.com/junegunn/fzf

Options

-m, --multi     # Enable multi-select with tab/shift-tab

Search syntax

'exact exact match ^start start with end.md$ end with

Examples

Execute binary under this directory

# with this shortcut, to select multiple items, just TAB an item
cat **<TAB> 
cd **<TAB>

Search file/folder with fd, select multiple items with fzf and copy to clipboard with pbcopy

fd --absolute-path | fzf --multi | pbcopy

Host names: names are extracted from /etc/hosts and ~/.ssh/config.

ssh **<TAB>

Set new alias fzfp to preview the selected item

alias fzfp="fzf --preview 'bat --style=numbers --color=always --line-range :500 {}'"
git branch -m <new name> # Rename current branch.
git branch -m <old> <new> # Rename other branch.
git branch | grep <regex> | xargs git branch -D # --delete --force Delete branch by regex pattern.
git clone <repository> <directory> # The repo is cloned into the specified directory.
git clone <repository> . # The repo is cloned into the current directory.
git commit -a # --all Commit all local changes.
git commit --amend # Amend last commit message.
# add --global after 'config' for global config
git config user.name "username"
git config user.email "email address"
# Set default pull strategy to auto stash and rebase.
git config pull.rebase true && git config rebase.autoStash true
git config core.editor "vim"
git config --get user.name
git config --get user.email
git config -l # --list List all variables set in config file.
git mv <source> ... <destination> # Move or rename a file, a directory, or a symlink.
# use `git log` to display commit-hash.
git revert <commit-hash>
git restore # Restore the file to the version in the latest commit
git restore . # Restore all files
git stash
git stash list
git stash --include-untracked # Include any untracked files in the stash.
git stash apply [<stash id>] # Apply latest stash.
git stash pop [<stash id>] # Like 'apply' but also remove the stash after apply.
git update-index --assume-unchanged <file>
git update-index --no-assume-unchanged <file>
git cherry-pick
git cherry-pick -x # Append a line that says "(cherry picked from commit …​)" to commit message.
##############
# References #
##############
cat <<EOF
https://git-scm.com/docs
https://gitexplorer.com
EOF
# Pull request
gh pr review --approve # Approve the pull request of the current branch
gh pr reivew -a
gh pr reivew -a <number> # Aprrove specific pull request
# Most `grep` options also AVAILABLE in `rg` too.
cat /usr/share/dict/words
grep -i '^.al.ation$' /usr/share/dict/words # Search for Incomplete Word (_AL_ATION) in the Dictionary
grep -x '.al.ation' /usr/share/dict/words # -x This is equivalent to putting ^...$ around all of the search patterns (--line-regexp)
rg --follow # To follow symlink
# Search hidden and ignore content
rg --hidden
rg -I # --no-filename
rg --no-filename
rg --no-ignore
rg -l # Only print the paths
rg --files-with-matches
rg -N -o # No line number and only matching pattern
rg -No
rg -u # equivalent to --no-ignore
rg -uu # equivalent to --no-ignore and --hidden
rg -v # --invert-match
# Search for content in specific file types
grep "search" *.txt *.csv
rg "search" --glob '*.txt' --glob '*.csv'
rg "search" --type txt --type csv
rg --type-list # show supported file globs
# Replacement -r, --replace
rg -r 'additional-text-$0' # prepend text to the entire match
rg -r '$1' # print only capturing group index 1
# Get specific html tag
rg -Nor '$1' 'href="(\S+)"'
rg -Nor '$1' 'img src="(\S+)"'
## Get text inside <title /> and use pandoc to convert html entity to plain text
rg -No '(?<=<title>)(.*)(?=</title>)' <(curl --silent 'url') | pandoc --from=html --to=plain
# Context Line Control
rg -B <num> # --before-context Show NUM lines before each match
rg -A <num> # --after-context Show NUM lines after each match
rg -C <num> # --context Show NUM lines before and after each match, equivalent to “-A <num> -B <num>”
##############
# References #
##############
cat <<EOF
https://github.com/BurntSushi/ripgrep/blob/master/GUIDE.md
EOF

Convert multiple inputs (images) with infinite loop and 750 ms deplay between sequence

convert -delay 75 -loop 0 input-* "$(uuidgen)".gif

Convert jpg to webp with resize and optimise options

magick <file> \
	-resize '6000' \
	-define webp:exact=true \
	-define webp:auto-filter=true \
	-define webp:emulate-jpeg-size=true 
	<output>.webp

Identify the image format

magick identify <files>

To get the print size in inches of an image at 72 DPI

magick identify -format "%[fx:w/72] by %[fx:h/72] inches" <file>

References

# Get active and owned GB servers from mullvad api.
curl --silent --compressed https://api.mullvad.net/www/relays/all/ | jq '.[] | select(.owned == true and .active == true and .country_code == "gb") | .hostname'
jq -r '.log.entries[].request.url' <file.json> # Retrieve urls from HAR file with raw output (-r) option.
echo 'a "b" c' | jq -Rs # Read raw input as a single long string and parse to json text. Similar to PHP's json_encode
# Assign new value to specific key
# For file, jq doesn't support in-place editing. Use `mktemp`, `mv` or `cp` to replace the target file.
curl --silent https://wtfismyip.com/json | jq ".YourFuckingCountryCode = \"Unknown\""
jq '[
.[] |
{
title: .snippet.title,
savedDate: .snippet.publishedAt,
url: "https://youtu.be/\(.contentDetails.videoId)",
thumbnail: .snippet.thumbnails.high.url
}
]' './Takeout/YouTube and YouTube Music/playlists/likes.json' # Parse Youtube's like playlist
# Add touch id support to sudo command. Just add 'auth sufficient pam_tid.so' at the TOP of `/etc/pam.d/sudo`.
# If pam_tid.so is not in `/etc/pam.d/sudo` then add it via `sed` to the top of the sudo file.
grep 'pam_tid.so' /etc/pam.d/sudo; if [[ $? > 0 ]]; then sudo sed -i -e '1s/^/auth       sufficient     pam_tid.so\n/' /etc/pam.d/sudo && cat /etc/pam.d/sudo; fi

# Start from Sonoma 14 https://mastodon.social/@StrangeNoises/110910261899874868
cd /etc/pam.d/
sudo cp sudo_local.template sudo_local
# and uncomment 'pam_tid.so' line
sudo vim sudo_local

# Print human-readable format. Without -p, it prints OK
plutil -p ~/Library/Safari/Bookmarks.plist
# Convert plist to json. Should use -o option to avoid overwrite to orginal plist
# -r to add whitespaces to make it more readable
plutil -convert json -r ~/Library/Safari/Bookmarks.plist -o /tmp/bookmarks.json

sudo scutil --set ComputerName "NewName" 								# Change computer name in case current user doesn't have this permission
scutil --dns 															# Show DNS config
scutil --nwi															# Show network info

softwareupdate --list --include-config-data     # Fetch software update info.

smbutil statshares -a		# Print the attributes of all SMB mounted shares (version, encryption algorithm)

uuidgen
printf "B`cut -c2- <(uuidgen)`" 										# Generate uuid begin with specific char

xattr <file …>      # display the extended attributes
xattr -c <file …>   # (c)lear all attributes
xattr -dr com.apple.quarantine /Applications/<app>						# (d)elete apple's quarantine (r)ecursively.

# https://wiki.mozilla.org/Firefox/CommandLineOptions
/Applications/Firefox.app/Contents/MacOS/firefox -url <url>
/Applications/Firefox.app/Contents/MacOS/firefox -private-window <url>     # Open link in Firefox using private mode

Image

sips -g all <input> 													# Get all details about image input.
sips --getProperty 'dpiWidth'                 # Get only width dpi value
# sips will override input. Use --out to output a new file.
sips -s format jpeg <input.not_jpeg> --out <output>.jpg					# Convert NON-jpg to jpg.
sips -Z <integer> <input> --out <output>								# Resample image so height and width aren't greater than specified size.

open -a ScreenSaverEngine.app 											# Enable screen saver.
man -t open | open -f -a Preview										# Display "open manual" in Preview.app from standard input (-f)

A/V

afinfo <audio_file>														# Audio file info

afplay <audio_file>														# Play audio file.
afplay /System/Library/Sounds/Blow.aiff									# Play system sound. Good for notification alarm.

afconvert <input.wav> -o <output.m4a> -f m4af -d aac					# Convert wav file to Apple MP4 Audio
afconvert -hf 															# Print a list of supported file/data formats

# Volume
osascript -e 'output volume of (get volume settings)'					# Get volume level
osascript -e 'set volume output volume 50'
osascript -e 'output muted of (get volume settings)' 					# Get mute status
osascript -e 'set volume output muted true' 							# Set mute status

say -o <output.(m4a|aac)> 'Hello world'
say -v '?' 																# obtain a list of voices installed in the system
say -v Serena 'The quick brown fox jumps over the lazy dog'				# Use Serena voice

CloudDocs (iCloud Drive)

Manage CloudDocs daemon

brctl download <path>
brctl evict <path>
# Download icloud files (work only sequential download)
fd --hidden '.icloud$' | while read file; do brctl download "$file"; done
fd --hidden '.icloud$' --threads 1 -x brctl download

Network

Retrieve dns information from system’s DNS cache, which is managed by mDNSResponder. Hint 💡: search “gethostbyname2” and “gethostent”.

dscacheutil -q host -a name www.apple.com

Safari

# Get all cloub tabs
sqlite3 -line ~/Library/Containers/com.apple.Safari/Data/Library/Safari/CloudTabs.db 'SELECT title, url, tab_uuid, device_name FROM cloud_tabs JOIN cloud_tab_devices WHERE cloud_tab_devices.device_uuid = cloud_tabs.device_uuid ORDER BY device_name'

# Delete specific tab by uuid
sqlite3  ~/Library/Containers/com.apple.Safari/Data/Library/Safari/CloudTabs.db "DELETE FROM cloud_tabs WHERE tab_uuid = '<uuidv4>'"

System administration

systemsetup is a higher-level tool for configuring system-level settings, while scutil is a more low-level.

systemsetup -help
systemsetup -printCommands # listing of commands without explanations

# manipulate ntp server
systemsetup -getnetworktimeserver
systemsetup -setnetworktimeserver <timeserver>
systemsetup -setnetworktimeserver time.apple.com

systemsetup -getsleep # get 'computersleep', 'displaysleep' and 'harddisksleep' values.
systemsetup -setcomputersleep <minutes>
systemsetup -setdisplaysleep <minutes>

systemsetup -getwakeonnetworkaccess

systemsetup -getremotelogin # check status of SSH. There is a flag to turn off SSH but doing so will result in the loss of the ability to administer the server using remote command line tools and SSH.

systemsetup -getcomputername # similar to `scutil --get ComputerName`
systemsetup -getlocalsubnetname

networksetup – configuration tool for network settings in System Preferences.

networksetup -help
networksetup -printCommands # listing of commands without explanations

# An asterisk (*) denotes inactive service.
networksetup -listnetworkserviceorder # shows ORDERED list of network services
networksetup -listallnetworkservices
networksetup -listallhardwareports # with device name and ethernet address
networksetup -listpreferredwirelessnetworks <device>
networksetup -listpreferredwirelessnetworks 'en1' # Should be 'wi-fi', use '-listallhardwareports' to get device name
networksetup -removepreferredwirelessnetwork 'en1' WhyYouAreHere
networksetup -removepreferredwirelessnetwork en1 "$(networksetup -listpreferredwirelessnetworks 'en1' | fzf | xargs)" # use 'xargs' to trim selected output from 'fzf'

networksetup -listlocations
networksetup -getcurrentlocation
networksetup -switchtolocation <location>

networksetup -getnetworkserviceenabled <networkservice>
networksetup -getnetworkserviceenabled 'Wi-Fi' # "Enabled" or "Disabled"
networksetup -getinfo 'wi-fi' # shows the IP address, subnet mask, router, and hardware address. Case-insensitive
networksetup -getinfo "$(networksetup -listallnetworkservices | fzf)" # use `fzf` to select network setvices
networksetup -getmacaddress 'Wi-Fi'
networksetup -getdnsservers 'Wi-Fi'
networksetup -setdnsservers 'Wi-Fi' 9.9.9.11 149.112.112.11
networksetup -setdnsservers 'Wi-Fi' 'empty' # clears all dns entries
networksetup -setmanual "Wi-Fi" 192.168.100.100 255.255.255.0 192.168.100.1

References

https://github.com/herrbischoff/awesome-macos-command-line What are the command line options for afconvert? Allow TouchID on your Mac to authenticate you for sudo access and iTerm config https://opensource.apple.com/source/DSTools/DSTools-162/dscacheutil/dscacheutil.m.auto.html https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/gethostbyname2.3.html man 8 systemsetup: https://support.apple.com/guide/remote-desktop/apd95406b8d/mac man 8 networksetup: https://support.apple.com/guide/remote-desktop/apdd0c5a2d5/mac

iperf3: perform network throughput tests

Options

-s    # Server mode
-c    # Client mode
-d    # Debug output
-R    # Reverse the direction of a test, so that the server sends data to the client
-p    # Port
-P    # Parallel

Examples

iperf3 -sd    # server mode with debug output
iperf3 -c ams.speedtest.clouvider.net -p 5205 -P 10   # specific port with 10 parallel connections
iperf3 -c lon.speedtest.clouvider.net -p "$(shuf -i '5200-5209' -n 1)" -R   # Reverse mode with random port

See also

Public iperf servers

nc ncat: utility reads and writes data across TCP or UDP network connections

basic: nc <host> [<port>]

Options

-l    # Listen for an incoming connection.
-u    # UDP
-v    # Verbose
-z    # Only scan for listening daemons, without sending any data to them.

Examples

nc -vz 192.168.0.1 1-5000 2>&1 | grep succeeded # Scan port 1-5000 w/o sending data and grab success output.

# Send/receive message
nc -l <port>    # Listener
nc <listener_ip> <same_port>  # Sender

# Send/receive file
nc -l <port> > output.file
nc <listener_ip> <same_port> < input.file

# Send/receive files with tarball
netcat -l <port> | tar xzvf -
tar -czf - * | netcat <listener_ip> <same_port>

See also

sqlite3 /etc/pihole/gravity.db 'SELECT * FROM domainlist' # query all domains list.
sqlite3 /etc/pihole/gravity.db 'SELECT * FROM vw_regex_blacklist' # query specific type. This case is blacklist.regex type.
sqlite3 /etc/pihole/gravity.db "
UPDATE domainlist SET
domain = 'google(tagservices|tagmanag)|tpc\.googlesyndication|app-measurement'
WHERE id = 8
" # update specific record
sqlite3 -line /etc/pihole/pihole-FTL.db "
SELECT domain, count(domain) as domain_count
FROM queries
WHERE status IN (2) and timestamp > "$(date -d '2 weeks ago' +%s)" and (domain NOT LIKE '%apple%' and domain NOT LIKE '%icloud%' and domain NOT LIKE '%aapl%')
GROUP BY domain
ORDER BY domain_count DESC
LIMIT 20
" # query top sites with specific timestamp and filter out Apple related domains.
sqlite3 /etc/pihole/pihole-FTL.db "
SELECT
domain,
status,
count(domain) AS domain_count
FROM queries
WHERE client = ''
GROUP BY domain
ORDER BY domain_count DESC
" # query domain with specific client
SEARCH_DOMAIN='wiki'; sqlite3 -line /etc/pihole/pihole-FTL.db "
SELECT *
FROM (
SELECT
domain,
client,
datetime(timestamp, 'unixepoch', 'localtime') AS local_date_time
FROM main.queries
WHERE domain LIKE '%$SEARCH_DOMAIN%'
ORDER BY timestamp DESC
LIMIT 200
)
ORDER BY local_date_time
" # search by domain and get output as a line with local date tiem, doamin and client.
# query all block items with #comment
sqlite3 -separator '' /etc/pihole/gravity.db 'select domain, "# " || comment from domainlist where type in (1, 3) and enabled = 1 order by domain'
# query all block items with /regex/ format
sqlite3 /etc/pihole/gravity.db 'select "/" || domain || "/" from domainlist where type in (1, 3) and enabled = 1 order by domain'
# query all allow items with #comment
sqlite3 -separator '' /etc/pihole/gravity.db 'select domain, "# " || comment from domainlist where type in (0, 2) and enabled = 1 order by domain'
# query all allow items with /regex/ format
sqlite3 /etc/pihole/gravity.db 'select "/" || domain || "/" from domainlist where type in (0, 2) and enabled = 1 order by domain'
pihole -c -r 60 # Calculates stats and displays to an LCD and update every 60 seconds
pihole -g # update domains
pihole tail # tail pihole's query log
## Domain list
cat <<EOF
https://gnuzilla.gnu.org/filters/blacklist.txt
https://firebog.net
EOF
pm2 start <file> \
--name <app_name>
pm2 restart <id|app_name|all>
pm2 reload <id|app_name|all>
pm2 stop <id|app_name|all>
pm2 ls
pm2 logs
pm2 monit # realtime dashboard
sudo raspi-config
############
# vcgencmd #
############
vcgencmd measure_temp
vcgencmd measure_clock arm
vcgencmd measure_clock core # GPU core
vcgencmd get_config total_mem
vcgencmd get_mem arm
vcgencmd get_mem gpu
# Reports whether the specified CODEC type is enabled.
vcgencmd codec_enabled H264
vcgencmd codec_enabled FLAC
##############
# References #
##############
cat <<EOF
https://www.raspberrypi.com/documentation/computers/os.html#vcgencmd
EOF

rsync

https://rsync.samba.org/

Options

-a        # Archive mode. This is equivalent to -rlptgoD
--delete  # Delete extraneous files from dest dirs
--exclude=PATTERN
-h, --human-readable
-n, --dry-run
--no-OPTION     # Turn off an implied OPTION
--progress
-r, --recursive
-v, --verbose
-z, --compress

# Preservations
-D              # --devices --specials
--devices       # Preserve device files
-g, --groups    # Preserve group
-l, --links     # Copy symlinks as symlinks
-o, --owner     # Preserve owner
-p, --perms     # Preserve permissions
--specials      # Preserve special files
-t, --times     # Preserve modification times

Examples

Local

Transfer all txt files to /tmp folder

rsync --times *.txt /tmp

Remote

Directory structure on remote machine.

Documents/
  file1.txt
  folder1/
    file2.txt

Transfer all files and FOLDER from (remote) machine in archive mode to local /tmp folder and create Documents folder in /tmp.

rsync -a remote:Documents /tmp
rsync -a remote:Documents/ /tmp/Documents
/tmp/
    Documents/
      file1.txt
      folder1/
        file2.txt

Trailing slash on the source means "copy the contents of this directory" WITHOUT Documents folder creation on local machine.

rsync -a remote:Documents/ /tmp 
/tmp/
    file1.txt
    folder1/
      file2.txt

Daemon

In order to connect to rsync daemon, remote system needs to have a configured daemon. Debian's default rsync daemon is /etc/rsyncd.conf

cat /etc/rsyncd.conf

max connections = 2
log file = /var/log/rsync.log
hosts deny = *

[pidl]
comment = Pi Download dir
path = /home/pi/Downloads
read only = false
list = true
hosts allow = 10.11.12.1 10.11.12.99

Download Pi files to local machine with :: or rsync://

rsync -a remote::pidl/ ~/Downloads
rsync -a rsync://pidl/ ~/Downloads

See also

https://download.samba.org/pub/rsync/rsync.1

https://download.samba.org/pub/rsync/rsyncd.conf.5

https://help.ubuntu.com/community/rsync

# sed is a LINE-oriented text processing utility: it reads text, LINE by LINE, from an input stream or file.
#################
# SUBSTITUTION #
#################
# s Substitute command
# /search/replacement/ Delimiter
# ?search?replacement? ? as a delimiter
# _search_replacement_ _ as a delimiter
# search Regular Expression Pattern Search Pattern
# replacement Replacement string
sed 's/good/bad/' <<EOF
It's a good good day.
EOF
# > It's a bad good day.
## with global (g) replacement, all matching occurrences in the line would be replaced.
sed 's/good/bad/g' <<EOF
It's a good good day.
EOF
# > It's a bad bad day.
sed 's/good //' <<EOF
It's a good day.
EOF
# > It's a day.
## To replace 2 words simultaneously
sed 's/good/new/; s/day/book/' <<EOF
It's a good day.
EOF
# > It's a new book.
# -e is POSIX standard.
sed -e 's/good/new/' -e 's/day/book/' <<EOF
It's a good day.
EOF
# > It's a new book.
##########
# DELETE #
##########
## Delete comment line.
sed '/^#/ d' <<EOF
# this is a comment
this is plain text.
EOF
# > this is plain text.
## Delete lines that are either blank or only contain spaces.
sed '/^ *$/ d' <<EOF
first line.
final line.
EOF
# > first line.
# > final line.
# character class [:class:] must be used INSIDE bracket []
sed '/^[[:space:]]*$/ d' <<EOF
first line.
final line.
EOF
# > first line.
# > final line.
###################################
# EDIT FILES IN-PLACE (non-POSIX) #
###################################
sed -i '.backup' 's/abc/def/' thisisfile.txt
## GNU
sed -i 's/abc/def/' thisisfile.txt # overwrite file
## FreeBSD and macOS
sed -i '' 's/abc/def/' thisisfile.txt # must specific empty extension to overwrite file
#######
# FAQ #
#######
cat <<EOF
Q: Remove comment (\#) and empty line
A: \` sed -e 's/[[:space:]]*#.*//' -e '/^[[:space:]]*$/ d' \` # 1st: remove from the # to the end of line. 2nd: delete blank line. Original empty line is also deleted.
https://stackoverflow.com/a/3350246
EOF
cat <<EOF
Q: Trim both ends
A:
sed -E 's/^[[:space:]]+|[[:blank:]]+$//g'
# Use sub-exression \1 - \9 in replacment to replace only pritable character, no space/blank.
sed -E -e 's/^[[:space:]]+([[:graph:]])/\1/ g' -e 's/([[:graph:]])[[:blank:]]+$/\1/ g'
EOF
cat <<EOF
Q: Convert webvtt to plain txt
A:
sed -E -e '/^([0-9]+:)?[0-9]{2}:[0-9]{2}.+(-->).+$/ d' -e '/^[0-9]+$/ d' -e '/^$/ d' -e '/^WEBVTT/ d' -e 's/<\/?[[:alpha:]]+>// g' -e 's/<c\.color[0-9a-fA-F]{6}>// g'
1st expression to remove cue timing
2nd expression to remove cue identifier
3rd expression to remove empty line
4th expression to remove the optional WEBVTT
5th expression to remove tags
6th expreesion to remove color tag
EOF
##############
# References #
##############
cat <<EOF
With various useful cases: https://www.grymoire.com/Unix/Sed.html
https://en.wikipedia.org/wiki/Sed
https://www.gnu.org/software/sed/manual/sed.html
https://www.freebsd.org/cgi/man.cgi?query=sed&manpath=FreeBSD+13.0-stable
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/sed.html
EOF
# backup db to specific path without worrying about locking mechanism (it uses transaction).
# https://stackoverflow.com/a/41744952
sqlite3 /etc/pihole/gravity.db '.backup /tmp/gravity.db'
# backup and vacuum. it's sql script so file path must have quotes.
sqlite3 /etc/pihole/gravity.db 'VACUUM INTO "/tmp/gravity.db"'
# dump db to plain SQL file and gzip it.
# https://sqlite.org/cli.html#converting_an_entire_database_to_an_ascii_text_file
sqlite3 /etc/pihole/gravity.db '.dump' | gzip -9 -c >gravity.sql.gz
# dump specific table
sqlite3 /etc/pihole/gravity.db '.dump adlist'

POSIX

uname: print system information

Options

-a		# All options
-m		# Machine hardware type
-n		# Nodename or hostname
-r		# Release
-s		# OS name. No option print this by default.
-v		# OS version

Examples

macOS

uname
Darwin

uname -a
Darwin NODE_NAME 21.4.0 Darwin Kernel Version 21.4.0: Fri Mar 18 00:45:05 PDT 2022; root:xnu-8020.101.4~15/RELEASE_X86_64 x86_64

uname -srv
Darwin 21.4.0 Darwin Kernel Version 21.4.0: Fri Mar 18 00:45:05 PDT 2022; root:xnu-8020.101.4~15/RELEASE_X86_64

Debian

uname
Linux

uname -a
Linux raspberrypi 5.10.103-v7l+ #1529 SMP Tue Mar 8 12:24:00 GMT 2022 armv7l GNU/Linux

uname -srv
Linux 5.10.103-v7l+ #1529 SMP Tue Mar 8 12:24:00 GMT 2022

See also

macOS

system_profiler: reports system hardware and software configuration

Options

-listDataTypes    # Lists the available data types
-json

Examples

system_profiler SPApplicationsDataType  # List of all applications (version, location)

system_profiler SPAudioDataType

system_profiler SPAirPortDataType     # Wi-fi (PHY modes, Airdrop, current network info, transmit rate)

system_profiler SPBluetoothDataType   # (chipset, supported services)

system_profiler SPDisplaysDataType    # Graphics/Displays

system_profiler SPEthernetDataType

system_profiler SPFirewallDataType    # (Apple Remote Desktop, SSH, Screen Sharing)

system_profiler SPHardwareDataType    # Hardware overview

system_profiler SPInstallHistoryDataType

system_profile  SPInternationalDataType # Language & Region (Siri, Calendar, Input, Units)

system_profiler SPMemoryDataType

system_profiler SPNetworkDataType

system_profiler SPNVMeDataType

system_profiler SPPowerDataType

system_profiler SPSoftwareDataType    # System Software Overview (kernel version, time since boot, computer name, user name, is SIP enabled)

system_profiler SPStorageDataType

system_profiler SPThunderboltDataType

system_profiler SPUSBDataType

See also

sw_vers: print macOS version information

Options

-productName
-productVersion
-buildVersion

Examples

sw_vers
ProductName:	macOS
ProductVersion:	12.3.1
BuildVersion:	21E258

sw_vers -productVersion
12.3.1

Unix-like

sysctl: get or set kernel state

Options

-A    # Equivalent to -o -a
-a    # List all the currently available non-opaque values
-h    # Format output for human
-n    # Show only variable values. This option is useful for setting shell variables.  For instance, to save the pagesize in variable psize, use: set psize=`sysctl -n hw.pagesize`
-o    # Show opaque variables (which are normally suppressed)

Examples

sysctl -hn hw.memsize
17,179,869,184

sysctl -n hw.model
Macmini8,1

sysctl -n hw.ncpu
6

sysctl -n hw.physicalcpu
6

sysctl -n hw.logicalcpu
6

sysctl hw.optional.x86_64
hw.optional.x86_64: 1

sysctl hw.optional.aes 
hw.optional.aes: 1

sysctl kern.maxproc
kern.maxproc: 4176

sysctl kern.version
kern.version: Darwin Kernel Version 21.4.0: Fri Mar 18 00:45:05 PDT 2022; root:xnu-8020.101.4~15/RELEASE_X86_64

sysctl -n machdep.cpu.brand_string
Intel(R) Core(TM) i5-8500B CPU @ 3.00GHz

sysctl -n machdep.cpu.features
FPU VME DE PSE TSC MSR PAE MCE CX8 APIC SEP MTRR PGE MCA CMOV PAT PSE36 CLFSH DS ACPI MMX FXSR SSE SSE2 SS HTT TM PBE SSE3 PCLMULQDQ DTES64 MON DSCPL VMX SMX EST TM2 SSSE3 FMA CX16 TPR PDCM SSE4.1 SSE4.2 x2APIC MOVBE POPCNT AES PCID XSAVE OSXSAVE SEGLIM64 TSCTMR AVX1.0 RDRAND F16C

sysctl vm.swapusage
vm.swapusage: total = 2048.00M  used = 1310.25M  free = 737.75M  (encrypted)

# Set kernel state, this will persist until the next reboot. Some system can be set via `/etc/sysctl.conf` to enabled whenever the system boots.  
sudo sysctl kern.maxprocperuid=4000

See also

head -c 20 # print the first 20 bytes of each file.
head -n 20 # print the first 20 lines instead of the first 10.
tail -c 20 # print the last 20 bytes.
tail -n 20 # print the last 20 lines, instead of the last 10.
tail -F <file> # Keep waiting for additional data to be appended and being followed (-F) has been renamed or rotated.
tail -r # print lines in reverse order. Non-POSIX. Equivalent to `tac`
head -n 22 | tail -n 11 # print the lines (from line number 12 to 22, both inclusive) for the input file by print the first 20 lines and then print the last 11 lines of first output.
cut -c 1-16 # print the FIRST SIXTEEN characters of each line of the given files.
cut -c 3- # print everything from the 3rd character to the end of each line.
cut -c2,7 # print the 2nd and 7th character from each line of text.
cut -c1-4 # print the FIRST FOUR characters.
cut -c13- # print the characters from 13th position to the end.
cut -f1-3 # Given a TAB delimited file with several columns (tsv format) print the FIRST THREE fields.
cut -d '.' -f 1 # print 1st field by using . (dot) as a field delimiter
rev | cut -d '.' -f 1 | rev # print last field by using . (dot) as a field delimiter
tac <file|stdin> # (cat) last line first
# tr(anslate). It searchs and replaces an input.
tr abcd wxyz # maps all characters: a => w, b => x, c => y and d => z
tr a-d w-z
tr A-Z a-z # Convert uppercase to lowercase
tr '[:upper:]' '[:lower:]'
tr -s ' ' # Squeeze repeated character to occurrence of that character. In this case, replace 'Hello World' to 'Hello World'
tr -s '\n' # Squeeze each sequence of repeated newlines to a single newline
tr -d ' ' # Remove character. In this case, 'Hello World' to 'HelloWorld'
tr -d '[:blank:]'
# paste is merge
paste -s <input> # Merge input with tab delimiter. In this case, 'Line1 Line2 Line3 Line4'
paste -s -d ';' <input> # Merge input with ';' delimiter. In this case, 'Line1;Line2;Line3,Line4'
printf "1\n2\n3\n" | paste -sd ',' - # Merge input from standard input (stdin) with ',' delimiter. In this case, '1,2,3'
# Escaped string for shell
printf '%q' "Character (computing) - Wikipedia"
# Character\ \(computing\)\ -\ Wikipedia
sort -u # Unique
sort -o <file> # Output file. This file can be the same as one of the input files #POSIX

Default prefix is ctrl + b

tmux new -s <session_name> # create new session
tmux ls
tmux a # attach
tmux detach # shortcut: <prefix> + d
<prefix> + t # big clock

Window management

<prefix> + c # create
<prefix> + w # list
<prefix> + n # next
<prefix> + p # previous
<prefix> + & # kill
<prefix> + , # rename current window

Pane management

<prefix> + ← ↑ → ↓     # Switch to pane in specific direction
<prefix> + ;           # Switch to previously active pane
<prefix> + o           # Switch to next pane in current window

<prefix> + %           # Split pane vertically
<prefix> + "           # Split pane horizontally
<prefix> + x           # Kill current pane

<prefix> + <alt> + ← ↑ → ↓  # Resize the pane in specific direction

References

https://gist.github.com/MohamedAlaa/2961058 https://thoughtbot.com/blog/a-tmux-crash-course

# [e]moji [i]dentify [p]rint [s]earch
uni e pray # name and CLDR data are searched. Handy than `search` cmd.
# name (cldr)
# 🙏 folded hands (ask, high 5, high five, please, pray, thanks)
# 📿 prayer beads (clothing, necklace, religion)
uni e -or pray cat bug
uni i ฿£$
# cpoint dec utf8 html name (cat)
# '฿' U+0E3F 3647 e0 b8 bf &#xe3f; THAI CURRENCY SYMBOL BAHT (Currency_Symbol)
# '£' U+00A3 163 c2 a3 &pound; POUND SIGN (Currency_Symbol)
# '$' U+0024 36 24 &dollar; DOLLAR SIGN (Currency_Symbol)
uni p Currency_Symbol
# cpoint dec utf8 html name (cat)
# '$' U+0024 36 24 &dollar; DOLLAR SIGN (Currency_Symbol)
# '¢' U+00A2 162 c2 a2 &cent; CENT SIGN (Currency_Symbol)
# '£' U+00A3 163 c2 a3 &pound; POUND SIGN (Currency_Symbol)
uni s pray
# cpoint dec utf8 html name (cat)
# '📿' U+1F4FF 128255 f0 9f 93 bf &#x1f4ff; PRAYER BEADS (Other_Symbol)

touch: change file access and modification times

If file does NOT exist: create NEW EMPTY file with current timestamps.

Options

-d <date_time>	# With format 'YYYY-MM-DD hh:mm:SS[.frac][tz]'
-t <time>	    # With format '[[CC]YY]MMDDhhmm[.SS]'
-a		        # Change the access time
-m		        # Change the modification time
-r <file>       # Use this file's times instead of current time

Examples

Set file to specific timestamp. -am can be omitted.

touch -am -d '2001-01-01 02:03:04' <file>

Create/update "target" file with last data access timestamp set to the same time as "ref_file" file instead of the current time.

touch -r ref_file target

See also

TODO: re-organise

file <file>			# Determine file type.
file /usr/bin/alias		# /usr/bin/alias: POSIX shell script text executable, ASCII text
file /bin/sh			# /bin/sh: Mach-O 64-bit executable x86_64
stat -x <file>			# display file info. -x is for macOS.
# extract modification year from file
stat -f '%Sm' -t '%Y' <file>	# BSD
stat -c %y <file> | cut -c 1-4	# GNU

# calculator 🧮
bc

# Truncate specific file.
cat true >| <file> # | will ignore noclobber option
:>| <file>
truncate -s 0 <file> # '-s 0' means size 0

# Change name (mv) with random filename
for target_file in *.jpg
do
	# new_file="$(gmktemp XXXXXXXXXX.jpg)"
	new_file="$(uuidgen).jpg"
    	mv -f -- "$target_file" "$new_file" # -f to overwrite `new_file`
done

# wc
wc -l <file> # count lines in files
wc -w <file> # count words in files
wc -m <file> # count characters in files with support of multibyte
ls -l | wc -l # count number of files

# netcat
nc -vz <hostname> <port> # just scan (w/o sending data) in verbose mode.

jot -r 20 1 20 # Print 20 numbers between 1-20.
jot -r 1 10 20 # Print a random number between 10-20.

shuf -i 1-20 # Shuffle number between 1-20 with 20 outputs.
shuf -n 5 /usr/share/dict/words # Pick first 5 lines from shuffled words file.

diff -y --suppress-common-lines <file1> <file2> # Diff side-by-side and hide common lines.
# compare alacritty.yml side-by-side and merge into new file.
sdiff ~/.config/alacritty/alacritty.yml <(curl --silent https://raw.githubusercontent.com/alacritty/alacritty/master/alacritty.yml) -o alacritty.tmp.yml

# tar + gz
tar -cf archive.tar <file1> <file2> <fileN> # (c)reate tar (f)ile.
# Tar is archive only format, to compress (with gzip) use this command.
tar -czvf archive.tar.gz <directory/> # (c)reate tar (f)ile and compress the resulting archive with g(z)ip with (v)erbose output. Note: czvf options should be in this order.
tar -cv - <directory/> | gzip > archive.tar.gz # same result with pipe method, "-" is stdout.
tar -cv - <directory/> | gzip -9 > archive.tgz # with best compression and standard short format.
tar -xfv archive.tar.gz # e(x)tract compression (f)ile to current directory.
# archive multiple files
fdfind --print0 --max-depth 1 --type file --extension sh | tar --create --gzip --verbose --file 'shell.tar.gz' --null --files-from -

# crontab
crontab -l | grep -E '^[[:digit:]]|^@|^\*' | sort -h # sort crontab by time, use [P]CRE and --[h]uman-numeric-sort
crontab -l | grep -vE '^#|^[[:space:]]*$' | sort -h # In[v]ert result to filter space (newline) and #

# xargs
# run multiple commands in xargs. This script will run sleep, print and say random second number.
shuf -n 1 -i 6-10 | xargs -I '{}' zsh -c "sleep {}; say {}; echo {};"

# create man page
groff -man -T utf8 <(curl --silent https://raw.githubusercontent.com/tmux/tmux/master/tmux.1) | less

#############
# Swap file #
#############

# [1] [2]
sudo service dphys-swapfile status
sudo vim /etc/dphys-swapfile # set swap size
## disable swap
sudo service dphys-swapfile stop
free # display system memory
sudo systemctl disable dphys-swapfile
## enable swap
sudo apt install dphys-swapfile
sudo systemctl start dphys-swapfile
sudo systemctl enable dphys-swapfile

##########
# Python #
##########

# create local http server. https://gist.github.com/willurd/5720255
python3 -m http.server <port_number>
python -m SimpleHTTPServer <port_number>

##############
# User limit #
##############
ulimit -a			# Get all user limits
ulimit -n			# Get current file descriptors limit
ulimit -u			# Get current process limit
ulimit -H -n			# Get hard limit
ulimit -S -n			# Get soft limit
ulimit -n 24000			# Set new limits for current shell
ulimit -u 4176

#######
# NTP #
#######

ntpq -p			# Print a list of the peers
ntpq -pn		# Same but in dotted-quad numeric format

#########################
# finds duplicate files #
#########################

fdupes -r .				# Search duplicates files for every directory given follow subdirectories
fdupes --omitfirst			# Omit the first file in each set of matches
fdupes -o 'name'			# Order files according to name (time|ctime|name)
fdupes --order 'time' --reverse		# Ordered by modification time in reverse order; new one first
# `--delete --noprompt` will PRESERVE THE FIRST FILE and delete the rest without prompting the user
fdupes --order 'name' --delete --noprompt
fdupes --order 'time' --reverse --delete --noprompt

########
# sudo #
########

# sudo password less for specific user
sudo visudo				# [5] add this to the bottom of file `$YOUR_USER ALL=(ALL) NOPASSWD: ALL`

##########
# zoxide #
##########

zoxide remove "$(pwd)"	# remove the current directory from the zoxide database

##############
# References #
##############

cat <<EOF
[1]: https://man7.org/linux/man-pages/man8/swapoff.8.html
[2]: https://manpages.ubuntu.com/manpages/bionic/man8/dphys-swapfile.8.html
[3]: https://github.com/adrianlopezroche/fdupes
[4]: How to change names of files in a directory to random generated names? https://askubuntu.com/a/1107088
[5]: Execute sudo without Password? https://askubuntu.com/a/147265
EOF

File and Path

Get absolute path of file. For example, retrieve path of syslog in /var/log/ and assume that we are in the log directory.

cd /var/log

echo $PWD/syslog
ls $PWD/syslog
# For system that has gnu's coreutils. These bins resolve symlink.
realpath syslog
readlink -f syslog

/var/log/syslog		# all above will return this line.

ls

ls -t # sort by time, newest first

watch: watch executes a program periodically

watch runs command repeatedly, displaying its output and errors.

Options

-n <seconds>	# Specify update interval 

Examples

Run the fd command every 600 seconds to list all files that have been modified in the last 24 hours.

watch --interval 600 "fd -l -t=file --changed-after '1day'"

Monitors the last 10 lines of the system log file /var/log/syslog. It updates every 60 seconds, showing recent changes to the file.

watch -n 60 tail -n 10 /var/log/syslog

See also

yt-dlp -a <list-of-urls-file> # inputs are separated by line break.
yt-dlp -g <url> # get url.
yt-dlp --skip-download --all-subs <url> # get subtitles.
yt-dlp -x <url> # convert video files to audio-only files.
yt-dlp -F # --list-formats List all avaialable formats.
yt-dlp -f <number> <url> # get specific format.
yt-dlp -f 'bestvideo[width<=3000]+bestaudio' # best video but no 4K.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment