环境
- zsh: 交互式 shell 使用 zsh 非常好用, 可以理解.
但是执行脚本时, 应当使用 bash. zsh 不兼容 bash, 如以下命令
A="aaa bbb"; ls $A在 zsh 中是cannot access 'aaa bbb', 而在 bash 中是cannot access 'aaa' ... cannot access 'bbb'.
能比 bash 还要晦涩, zsh 可谓让人起敬.
脚本
I’ve never seen any language more obsecure than bash… probably except English. – Hoblovski
寻找当前目录下所有的 ASCII 文本文件
$ find . -type f -exec file '{}' \; | ag "ASCII text" | awk -F: '{print $1}'
或者使用 cut, 一般情况下 cut 比 awk 快
$ find . -type f -exec file '{}' \; | ag "ASCII text" | cut -d: -f1
递归替换某个字符串
一般替换字符串都只发生在文本文件上, 因此使用 ripgrep rg 而非 grep. 它比 ag 和 grep 都快.
$ rg stdio -l | xargs sed -i 's/stdio/llstdio/g'
或者也可以
$ find . -type f -exec sed -i 's/stdio/llstdio/g' {} +
显示所有发生超过 100000 次的中断
发生次数是所有核上之和, 使用 /proc/interrupts 内核文件来访问中断发生次数.
$ awk '$2+$3+$4+$5 > 10000 || NR == 1 {print $0;}' /proc/interrupts
打印两个目录中有那些文件不同
这里要求文件在两个目录中都存在, 但是不同.
也就是 A/path/path/file 和 B/path/path/file 都存在, 但是不同.
$ diff -rq linux-4.17.3 linux-4.17.3-mychanges | awk '$NF=="differ" {print $2, $4;}' | column -t
同样可以使用 cut
$ diff zfs_v3.12/ zfs_v3.13/ -rq | cut -d\ -f2,4 | column -t
当然一般使用 meld 就好.
统计 Linux 内核中使用了多少 down_interruptible
也是使用 awk. 不过需要注意, 本文并不是 awk 专场.
ag -cw down_interruptible | awk -F: 'BEGIN{s=0} {s+=$2} END{print s}'
顺带一提, 4.16 内核中使用了 147 次 down_interruptible.
从多个备选版本中选取程序
这个我只能用 if 做, 不知道有没有方法用 && 做.
$ if clang-3.9 --version; then CL=clang-3.9; elif clang-3.8 --version; then CL=clang-3.8; else CL=""; fi
$ echo $CL
Advanced Bash Scripting
给出了更好的方法, 就是使用 type 命令.
后来我看 riscv toolchains 中给出了更好的方法
# Use gmake instead of make if it exists.
MAKE=`command -v gmake || command -v make`
从 txt 生成 pdf
如果只有英文倒是可以使用 vim, 但是有中文的话不知道为什么就会有乱码.
可能是因为我用的系统是英文的缘故吧. 不过可以使用 libreoffice
$ libreoffice --convert-to "pdf" xxx.txt
寻找某个 C 项目中用了那些宏来完成条件编译
$ ag --nofilename '#ifn?def' | sed 's@^\s*#\s*ifdef\s\+\(\w*\).*@\1@' | sort | uniq
不含历史的 git clone 加速
$ git clone https://github.com/torvalds/linux.git --depth=1 && rm linux/.git -rf
查询每个 host 访问 nginx 的次数并排序
居然有脚本小子想访问我的 vps…
$ awk '{print $1}' /var/log/nginx/access.log.1 | sort | uniq -c | sort
去掉文件前缀
$ for X in *; do mv $X ${X##learning-}; done
vim 强制设置高亮类型
:set syntax=c
cd 之后自动 ls
这个设置舒服啊, 最好加到 zshrc / bashrc 里面去
cd() {
builtin cd "$@" && ls -F
}
命令行下 wifi 操作
Ubuntu 操作网络用的是 NetworkManager, 命令行下使用其 nmcli
$ nmcli dev wifi # 扫描可用 AP
$ nmcli dev wifi con SSID # 连接到 wifi
$ nmcli con up SSID # 连接一个曾经连过的 wifi, 不用输密码
将文件名中的换行符替换成空格
使用 rename 命令. stackoverflow 上面的答案不准确.
$ rename 's/\n/ /g' *
还可以用 rename 来做文件名小写, 如
$ rename 'y/A-Z/a-z/' *
寻找当前目录下最近一分钟内改变的文件
通常对工具做黑箱分析的时候会有这样的需求.
$ find . -cmin -1
检查 gcc 的预定义宏
从 riscv glibc 的角落中发现的, 他居然用这个东西然后 grep XLEN 来检查目标的 XLEN.
$ gcc -E -xc -dM /dev/null
检查 gcc 的默认 include 路径
$ echo | gcc -E -Wp, -v -
惊喜
$ echo c3VycHJpc2UgbW90aGVyZnVja2VyCg== | base64 -d | spd-say -e >/dev/null
vim 在 normal mode 下复制某一行内容到光标行之下
:76t.
gcc 的选项默认值
$ gcc -Q --help=target
$ riscv64-unknown-linux-gnu-gcc -Q --help=target
比如用来找出默认的 arch.
检查 ELF 的 .comment
readelf -p .comment hello_world
简化 locate 输出
locate 输出经常很大一串, 这种时候我希望找到相关的路径就好
$ locate mqueue | cut -b -40 | sort | uniq
ld 默认的库搜索路径
$ ld --verbose | ag SEARCH
检视端口使用情况
$ netstat -tlunp
抽取第 A 字节开始 N 个
$ dd ibs=1 skip=0 count=512 if=ubuntu.iso of=mbr
反汇编 raw 二进制文件
$ objdump -D -b binary -mi386 -Maddr16,data16 mbr
将 pdf 转换成 png
通常用来发到中国使用的群聊中.
$ xelatex git.tex && pdftoppm git.pdf outputname -png && convert -append outputname-*.png out.png
上一条命令的第n个参数
$ echo 1 2 3
$ echo !!:0 !!:1 !!:2
显示 apt 安装软件的详情
$ apt-cache show vim
搜索 man
一个词可能在不同的 man section 中出现
$ man -k ulimit
搜索 errno
perror 也是命令行工具
$ perror 19
限制进程使用的内存
简单的就是 ulimit, 其不同选项可以用 ulimit -a 显示.
$ ulimit -v 1536 chrome
让 make 打印失败的命令
$ make SHELL="/bin/bash -x"
寻找提供某个文件的包
$ dpkg -S c++config.h
让 sed 做 line filter
$ rg -l -- -posix-runtime | sed '/^test/d' # negative filter
$ rg -l -- -posix-runtime | sed -n '/^test/p' # positive filter
检查系统安装了那些字体
$ fc-list
vim 替换模式为换行
:%s/^M/\r/g
某进程打开的文件: lsof 的快速使用方法
lsof -nP -p PID
~~
## 检视 screen-256color 的颜色
for i in {0..255}; do printf “\x1b[38;5;${i}mcolor%-5i\x1b[0m” $i ; if ! (( ($i + 1 ) % 8 )); then echo ; fi ; done
## 获得随机浮点数
echo “scale=10; ${RANDOM} / 65536” | bc ~~
并行运行
之前并行运行都是手动 ./task &,但直接使用 GNU parallel 就很舒服了。
尤其是 parallel 会保证并行运行的每个 job 的 stdout 输出不会混杂在一起。
cat >t.sh <<'EOF'
f() { sleep $1 ; echo $1 ; sleep 4 ; echo $1 ; }
export -f f
parallel --halt now,fail=1 f ::: `seq 4`
EOF
bash t.sh
cat 的 heredoc 不要 shell expand
如上,cat <<'EOF' 注意单引号。