Believe it or not, the shell script is getting more impactful in the DevOps era!
marp | theme | paginate |
---|---|---|
true |
gaia |
true |
The Art of Command Line
2021-02-22
Kenta Yamamoto (@i05)
Unix Philosophy – “The Art of UNIX Programming” (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
- or consider installing
$ 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
cd
s!- rupa/z, or
- wting/autojump
- Remote repository management – let the tool decide where to locate the cloning repositories
Recommended commands:
jq
awk
rsync
time
watch
Linter:
$ echo "Thank you!"
コメントを投稿するにはログインしてください。