bash knack - hanyong/note GitHub Wiki
bash 小技巧
修改 xterm 终端标题
可使用特殊 xterm 序列修改终端标题, 参考: http://tldp.org/HOWTO/Xterm-Title-3.html
* ESC]0;stringBEL -- Set icon name and window title to string
* ESC]1;stringBEL -- Set icon name to string
* ESC]2;stringBEL -- Set window title to string
where ESC is the escape character (\033), and BEL is the bell character (\007).
参考 ubuntu 默认的做法, 是将此特殊序列添加到 $PS1
变量头部, 每次输出 PS1 时自动设置和更新终端标题。
对未进行此设置的系统, 按照 PS1 转义序列的写法, 在 /etc/bashrc
或 .bashrc
末尾添加如下内容即可:
PS1='\[\e]0;\u@\h:\w\a\]'"${PS1}"
参考上述说明, 如果只修改标题, 可将 0
改成 2
。
sed -r -e $'$ a\\n''PS1='''\[\e]2;\u@\h:\w\a\]'''"${PS1}"' -e '/^PS1='''\[\e][0-2];.*?\a\]'''"${PS1}"/ d' ~/.bashrc -i
重新进入当前目录
cd .
当前目录被删除重建后, 当前目录信息不再有效, 如 ls
报错或看不到文件,
cd .
重新进入当前目录后解决此问题.
列举隐藏文件
清空当前文件夹:
rm -rf * .[^.]*
列出当前目录文件, 忽略部分文件
find -maxdepth 1 -name . -o -name .git -o -name vendor -o -print
一个稍微简化的方法是:
ls -A | grep -Fwv -e .git -e vendor
>但当这样会使局部匹配的文件也被排除.
可封装成脚本 `lsno`:
```sh
#!/bin/bash
# 列出当前目录文件, 但排除参数列表指定的文件
a=( find -maxdepth 1 -name . )
for e in "${@}" ; do
# basename transform ".git/" or "./.git/" to "git"
a=( "${a[@]}" -o -name "$(basename "${e}")" )
done
a=( "${a[@]}" -o -print )
exec "${a[@]}"
ls 命令原生支持 --hide
选项,但只在列出目录子项时生效,与 -a
, -A
使用时无效,对参数输入项无效。
--hide=PATTERN
do not list implied entries matching shell PATTERN (overridden by -a or -A)
打印调试信息
bash -x a.sh
env SHELLOPTS=xtrace xxx
启动 bash 前设置 SHELLOPTS
显式打开 set
设置项, 并且能递归到子进程.
启动 bash 后对应值为所有开启的设置项.
$ echo $SHELLOPTS
braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor
$ SHELLOPTS=xtrace bash -c 'echo $SHELLOPTS'
bash: SHELLOPTS: 只读变量
braceexpand:hashall:interactive-comments
$ env SHELLOPTS=xtrace bash -c 'echo $SHELLOPTS'
+ echo braceexpand:hashall:interactive-comments:xtrace
braceexpand:hashall:interactive-comments:xtrace
```
相似的 `BASHOPTS` 对应 `shopt` 设置项.
## 字符串数组拼接
参考: http://stackoverflow.com/questions/1527049/bash-join-elements-of-an-array
bash 扩展 `"${argv[*]}"` 时会使用 `IFS` 的第一个字符进行拼接,
利用这个特性可修改 `IFS` 实现字符串数组拼接。
为了不影响 bash 的正常功能, 应该只在实现拼接的局部范围内修改 `IFS`, 可使用函数或子 shell 限制修改 IFS 的范围.
```
$ x=( a b c )
$ echo $( IFS=, && echo "${x[*]}" )
a,b,c
```
> **注意** : `IFS` 是由 bash 识别和实现, 而不是 echo。要在 bash 中修改 `IFS`, `IFS=,` 要独立成一个语句.
也可以直接调用 `bash -c`, 因为数组型变量不能直接使用环境变量传递, 可使用命令行参数传递.
```
$ bash -c 'IFS=, && echo "$*"' -c a b c
a,b,c
```
另一个办法是使用 `printf` 命令,
当 `printf` 的实际参数个数多于格式化字符串参数个数时, 会循环复用格式化字符串。
因此, 格式化字符串只有一个参数, 即可应用于所有实际参数.
```
$ x=$(printf "%s," a b c)
$ echo "${x::-1}"
a,b,c
```