Skip to content

Instantly share code, notes, and snippets.

@ymkjp

ymkjp/deck.md Secret

Last active February 22, 2021 05:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ymkjp/d401b492388ba9d50e5a778b5318d0f4 to your computer and use it in GitHub Desktop.
Save ymkjp/d401b492388ba9d50e5a778b5318d0f4 to your computer and use it in GitHub Desktop.
marp theme paginate
true
gaia
true

The Art of Command Line

2021-02-22

Kenta Yamamoto (@i05) This work is licensed under a Creative Commons Attribution 4.0 International License


Unix Philosophy - "The Art of UNIX Programming" (2003)

raymond-2003


Make each program do one thing well. To do a new job, build afresh rather than complicate old programs by adding new features.

$ history | awk '{ print $2 }' | sort | uniq -c | awk '$1>1' | sort -r | head
    791 g
    172 cat
    115 git
     83 echo
     71 brew
     70 yarn
     68 ll
     50 dig
     49 gcloud
     43 jj

For example, you have to sort the output before uniq because they only do one thing:

$ history | awk '{ print $2 }' | sort | uniq -c | awk '$1>1' | sort -r | head

Execute a shell script:

#!/usr/bin/env bash
# command-ranking.sh
set -euo pipefail
history | awk '{ print $2 }' | sort | uniq -c | awk '$1>1' | sort -r
$ chmod u+x ./command-ranking.sh
$ bash ./command-ranking.sh | head

Interface - standard streams:

  • STDIN
  • STDOUT
  • STDERR
$ time curl -IL https://example.com/ 2>&1 > file.txt
$ time curl -IL https://example.com/
...
curl -IL https://example.com/  0.02s user 0.01s system 5% cpu 0.467 total

Parameters - $0, $1, $#, $@

#!/usr/bin/env bash
# sample.sh
cat -
echo "file=$0, 1st-arg=$1, 2nd-arg=$2, arg-num=$# args=$@"
$ echo "Hello" | bash $(pwd)/sample.sh foo bar baz
Hello
file=/Users/kyamamoto/src/bitbucket.org/i05/support/sample.sh, 1st-arg=foo, 2nd-arg=bar, arg-num=3 args=foo bar baz

Sounds of Silence - $?

$ touch ~/tmp/sample.txt
$ echo $?
0
$ mv no-such-file.txt /tmp/
mv: cannot stat 'no-such-file.txt': No such file or directory
$ echo $?
1

Subroutine - $(command)

$ curl "https://jpnic.rdap.apnic.net/ip/$(dig +short myip.opendns.com @resolver1.opendns.com)" \
| jq .

Construct argument list - xargs:

$ find . -type f -name "*" ! -path '*/.svn/*' ! -path '*/.git/*' -print0 \
| xargs -0 grep --ignore-case --line-number 'foo'

Parallel execution - xargs:

$ find . -type f -not -name '*.bz2' -print0 \
| xargs -0 -L 1 -P $(sysctl -n hw.ncpu) bzip2

Multibyte encoding - nkf:

$ find . -type f -name "*.txt" | xargs nkf --guess
$ find . -type f -print0 | xargs -0 nkf --overwrite -w

Multiline:

TEXT_LIST=$(cat << EOF
__HERE_DOCUMENT__
__HERE_DOCUMENT__
EOF
)

Runs everywhere:

case "${OSTYPE}" in
# Mac
darwin*)
    [ -f ~/.zshrc.osx ] && . ~/.zshrc.osx
    ;;
# Linux
linux*)
    [ -f ~/.zshrc.linux ] && . ~/.zshrc.linux
    ;;
esac

Pitfall

  • Mac - BSD
    • or consider installing brew install gnu-sed instead
$ LANG=C find . -type f -name "*" ! -path '*/.svn/*' ! -path '*/.git/*' -print0 \
| xargs -0 sed -i '~' -e 's///gi'
  • Linux - GNU
$ find . -type f -name "*" ! -path '*/.svn/*' ! -path '*/.git/*' -print0 \
| xargs -0 sed -i -e 's///gi'

Pitfall

  • Mac - BSD
$ LANG=C git ls-files -z | xargs -0 sed -i '' -e 's///gi'`
  • Linux - GNU
$ git ls-files -z | xargs -0 sed -i -e 's///gi'

Git subcommands:

$ git grep 'Could not find the specified attachment on the server'

Release your brain resource:

  • Easily navigate directories - go with fewer cds!
  • Remote repository management - let the tool decide where to locate the cloning repositories

Recommended commands:

  • jq
  • awk
  • rsync
  • time
  • watch

Linter:


$ echo "Thank you!"


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment