macOS Catalina(10.15) 之前默认是 bash,之后改成了 zsh;Why#
由于 license 问题,Mac bash仍然停留在 v3.2.57(GPLv2、2005),而可用的 bash 最新版到了 v5.*(GPLv3、2025)。
zsh license 对 Apple 友好,且最兼容 bash。Then#
切换到 zsh 其实是无感的,而且能安装 oh-my-zsh(莫非有 apple 暗里支持)也是很香的。如果想要体验新版 bash,可以使用 homebrew 安装。Tips#
shell进程替代<()和>()#
<() - 将命令的输出作为输入提供给其他命令。
<blockquote>() - 允许一个命令将其输出写入到另一个命令的输入中。</blockquote>
# examples
diff <(command1) <(command2)
paste <(command) <(command)
cat file.txt > >(tee output1.txt) > output2.txt
cat 反模式#
# wrong
cat some_file | grep foo
# yes
grep foo some_file
# yes
grep foo <some_file
# 合并标准输入+文件, - 指代占位符
echo yes |cat some_file - some_file2
Commands#
cpulimit#
限制进程cpu使用的命令
经过测试
- freebsd 下无作用;
- macOS 下运行 `cpulimit -l <number> <command>`;对已经存在的进程不起作用;
$PATH#
以zsh为例,取值来自
- /etc/paths 和 /etc/path.d/*:这部分是系统值,包括
- .zshrc中添加的path variables,包括
- `export PATH=...`
- 其他如 fnm 通过执行 `eval "$(fnm env --use-on-cd --shell zsh)"`
autoload vs source#
autoload:让Shell在function第一次调用的时候加载;source:立刻执行脚本。Main difference between SHELLs#
Array#
| Functionality |
Bash syntax |
Idiomatic zsh syntax |
Expansion |
| First element |
${a[0]} |
$a[1] or ${a[1]} |
first |
| Second element |
${a[1]} |
$a[2] or ${a[2]} |
second |
| Last element |
${a[${#a[@]}-1]} |
$a[-1] or ${a[-1]} |
last |
| Length |
${#a[@]} |
$#a |
5 |
| All the elements |
"${a[@]}" |
"${a[@]}" or "${(@)a}" |
first second third (empty word) last |
| All the non-empty elements |
|
$a |
first second third last |
Glob qualifiers#
| expression |
matching / example |
desc |
| foo*(.) |
foo* |
-r-- or lr-- |
| foo*(*.) |
foo* |
-r-x |
| foo*(-.) |
foo* |
-r-- |
| foo*(-@) |
foo* |
lr-- |
| foo*(om) |
foo* |
sort by modified time |
| foo*(om[1,10]) |
foo* | sort | head -10 |
|
| foo*(Lm+1) |
foo* | filter size > 1M |
|
| foo*(N) |
foo* or empty list???? |
实测下来返回所有!!! |
| *(D) |
|
show hidden files too(except . and ..) |
| foo/bar/*(:t) |
foo/bar/aa.txt => aa.txt |
foo/bar trimmed |
| foo/bar/*(.:r) |
foo/bar/a.txt=>foo/bar/a |
extension trimmed |
| foo*.odt(e\''REPLY=$REPLY:r.pdf'\') |
foo.odt => foo.pdf |
|
| foo*.txt~foobar* |
|
~ means excluding;zsh 独有
|
| image<->.jpg(n) |
image100.jpg |
n means glob qualifier;zsh 独有
|
mass-rename files#
zsh provides a very convenient tool: the zmv function. Suggested for your .zshrc:
autoload zmv
alias zcp='zmv -C' zln='zmv -L'
# Example:
zmv '(*).jpeg' '$1.jpg'
zmv '(*)-backup.(*)' 'backups/$1.$2'