Skip to main content

Shell FAQ

# YYYY-mm-DD-HH-MM
date +"%Y-%m-%d-%H-%M"

tar -czvf backup-$(date +"%Y-%m-%d-%H-%M").tar.gz ./data/ # 备份
tar -xzvf backup.tar.gz -C ./restored # 恢复
tar -I zstd -xvf archive.tar.zst # zstd

apk add procps-ng
ps aux
ps -ef e
# -E error: unsupported SysV option
ps -e -o 'pid,ppid,comm,args,user,uid' --sort pid
  • prompt
    • PS1 - primary
    • PS2 - secondary
    • PS3 - select
    • PS4 - debug
    • % non root, # root

ip

ip -o -4 addr show | grep -v veth | awk '{print $2, $4}'

skip first n line

tail -n +1

sort in place

# -o 可以,不要 > file
sort -o file{,}

tree utf8 chartset

# -N Print non-printable characters
tree -N

tree exclude

tree -I 'containerd|docker'
tree -I 'node_modules|cache|test_*'

tree -L 3 -I 'node_modules*|cache*'

shebang

for bash

#!/usr/bin/env bash

posix shell

#!/bin/sh

获取一个 Tab 字符

echo -ne \\t | pbcopy

找到最大的文件

find . -printf '%s %p\n' | sort -nr | head
find . -maxdepth 1 -printf '%s %p\n' | sort -nr | head
du -a . | sort -nr | head

文件时间信息

touch file
stat file
TZ=UTC stat -c '%y %n' file
date -r file +%s
# [[CC]YY]MMDDhhmm[.ss]
touch -a -m -t 203801181205.09 file
touch -d "2012-10-19 12:12:12.000000000 +0530" file

crtime - birt time

inode=$(stat -c %i test)
# stat 信息
debugfs -R "stat ${inode}" /dev/sdb1
# 危险操作
umount /dev/sdb1
debugfs -w -R "set_inode_field ${inode} crtime 200001010101.11" /dev/sdb1

pwd vs cwd

type -a pwd
--
builtin pwdecho $PWD
/bin/pwdpwd -P
getcwdreadlink -f /proc/self/cwd

doas vs sudo

  • doas
    • 95% of the features of sudo with a fraction of the codebase
    • ~1000 LOC
  • sudo
    • ~18K LOC
    • 依赖很多 - eventlog, iolog, logsrv, protobuf-c, zlib
    • logsrvd
    • 功能多一些 - 不一定会用得到

string include/match

[[ 'abcd' = *'bc'* ]] && echo yes
[[ 'abcd' =~ 'bc' ]] && echo yes
str=abcd [ -z "${str##*bc*}" ] && echo yes

trim space

echo "   lol  " | xargs
# 不会 trim 换行
echo -e " lol\r\n " | xargs | hexdump -C
# 移除所有空白
echo -e 'a b c\r' | tr -d '[:space:]'
# trim left - sed 不能替换 \r\n
echo -e ' \r\nabc\r\n ' | sed -e 's/^[[:space:]]*//'
# trim right
echo -e ' abc ' | sed -e 's/[[:space:]]*$//'

Terminal vs Console vs Shell

  • console = physical terminal
    • 物理实体
  • terminal = tty = teletype = text input/output environment
    • 链路协议接口
  • shell = command line interpreter
    • 上层抽象行为概念
    • 逻辑协议

基于时间搜索

# 修改时间在某个时间点之前的目录
find . -maxdepth 1 -type d -not -newermt 2022-01-01 -ls
# 递归删除
find . -maxdepth 1 -type d -not -newermt 2022-01-01 -exec rm -r {} ';'

修复一般文件和目录 mod

find . -type d -exec chmod 0755 {} \;
find . -type f -exec chmod 0644 {} \;

# 修复 某个 owner
find . -type d -user harry -exec chown daisy {} \;

shell vs python

  • shell - 必知必会
    • 让简单的事情 非常简单,让复杂的事情 非常复杂
    • 复杂过后可维护性差
    • 核心优势在于 compose/组合/联结 各种工具
    • 环境可预期
    • 工具 不一定完全兼容
      • posix/gnu/busybox/coreutils/findutils/util-linux
  • python - 补充扩展
    • 难度适中,可维护
    • 目前大多 linux 环境都有安装 python
    • python 也是 shell 一部分

zsh vs bash

vs.zshbash
interactive shell.zshrc.inputrc,.bashrc
login shell.zprofile.profile,.bash_profile
key bindingbindkey -> zle.inputrc bind -> readline
prompt PS1 escapePS1 - % 转义PS1 - ``` 转义
promot commandprecmd + preexec hookPROMPT_COMMAND
array indexstart from 1start from 0
  • zsh
    • 多用于用户环境
      • 交互更好
      • 功能更多
  • bash
    • 多用于服务端环境
      • 默认
      • 稳定

tee stderr

echo message | tee -a /dev/fd/2 > /dev/null

Sort Large File

split -l 1000000 in.txt chunk
for X in chunk*; do sort < $X > sorted-$X; done
sort -m sorted-chunk* > out.txt

# 清理
rm chunk* sorted-chunk*

arch

uname -m # x86_64, i686, arm, aarch64 - cpu type/arch
uname -s # Linux, Darwin - os type
uname -s | tr '[:upper:]' '[:lower:]'

# AlpineLinux
apk --print-arch

# debian/ubuntu
dpkg --print-architecture # amd64
arch # from coreutils, arch of the current terminal

# Golang
go env GOARCH # arm64, amd64
# GCC
gcc -dumpmachine # x86_64-linux-gnu, arm64-apple-darwin23.5.0
# NodeJS
node -p process.arch # arm64
# Java
java -XshowSettings:properties -version | grep os.arch
architecture=""
case $(uname -m) in
i386 | i686) architecture="386" ;;
x86_64) architecture="amd64" ;;
# apk --print-arch
arm) dpkg --print-architecture | grep -q "arm64" && architecture="arm64" || architecture="arm" ;;
esac

detect

if [ -n "$ZSH_VERSION" ]; then
echo "zsh"
elif [ -n "$BASH_VERSION" ]; then
echo "bash"
else
# assume something else
fi

case $SHELL in
*/zsh)
echo "zsh"
;;
*/bash)
echo "bash"
;;
*) ;;
# assume something else
esac
  • FCEDIT
    • fcsh
  • KSH_VERSION
    • ksh
  • PS3
    • ps3sh

PATH

  • /etc/paths
  • /etc/paths.d

macOS

  • /usr/libexec/path_helper
/usr/local/bin
/System/Cryptexes/App/usr/bin
/usr/bin
/bin
/usr/sbin
/sbin
/etc/paths.d/10-cryptex
/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin
/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin
/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin