环境
- 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'
注意单引号。