前言
Linux在软件开发中经常被使用到,在远程开发中,会经常使用到他的bash。因此一个好的bash配置可以极大地便利对Linux的使用。如下是一份我经常使用的bash配置以及zsh版本的配置。
配置
bash配置
在Linux下使用bash配置可以直接将下面内容放到 custom.sh 文件中,然后放到 /etc/profile.d/ 路径下。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
# ==========================================
# 1. 基础环境与语言设置
# ==========================================
export LANG=en_US.UTF-8
export LC_ALL=en_US.UTF-8
export EDITOR='vim' # 默认编辑器,也可以改成 nvim 或 emacs
# ==========================================
# 2. 增强版历史记录管理 (告别不小心冲掉记录的烦恼)
# ==========================================
# 增加历史记录容量(默认通常只有 1000)
export HISTSIZE=50000
export HISTFILESIZE=100000
# 忽略连续重复的命令,以及以空格开头的敏感命令
export HISTCONTROL=ignoreboth:erasedups
# 实时追加历史到文件,而不是等到终端关闭
shopt -s histappend
# 每次按回车时自动同步多终端历史
export PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND"
# ==========================================
# 3. 终端颜色与炫酷的提示符 (PS1)
# ==========================================
# 开启 ls 和 grep 的颜色支持
if [ -x /usr/bin/dircolors ]; then
test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
alias ls='ls --color=auto'
alias grep='grep --color=auto'
alias fgrep='fgrep --color=auto'
alias egrep='egrep --color=auto'
fi
# 一个兼顾美观与实用(包含高亮用户名、路径、时间)的提示符
if [ "$UID" -eq 0 ]; then
# root 全部红色
export PS1='\[\e[1;33m\][\D{%Y-%m-%d %H:%M:%S}]\[\e[0m\] \[\e[1;31m\]\u@\h:\w#\[\e[0m\] '
else
# 普通用户 黄时间+绿用户+蓝路径
export PS1='\[\e[1;33m\][\D{%Y-%m-%d %H:%M:%S}]\[\e[0m\] \[\e[1;32m\]\u@\h\[\e[0m\]:\[\e[1;34m\]\w\[\e[0m\]\$ '
fi
# 长路径只显示最后两级
export PROMPT_DIRTRIM=2
# ==========================================
# 4. 常用别名 (Aliases) - 拯救你的手指
# ==========================================
# 更直观的 ls
alias ll='ls -alF'
alias la='ls -A'
alias l='ls -CF'
# 安全保障(操作前确认)
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
# 系统监控快捷键
alias df='df -h'
alias free='free -m'
# 快速返回上级目录
alias ..='cd ..'
alias ...='cd ../..'
alias ....='cd ../../..'
# 便捷工具
alias path='echo -e ${PATH//:/\\n}' # 格式化输出 PATH,方便排查路径问题
alias myip="curl -s ifconfig.me; echo" # 快速查看外网 IP
alias python='python3'
alias pip='pip3'
# ==========================================
# 5. 效率倍增的自定义函数 (Functions)
# ==========================================
# 功能:创建一个目录并直接进入该目录
# 用法:mkcd my_project
mkcd() {
mkdir -p "$1" && cd "$1"
}
# 功能:万能解压工具,自动根据后缀调用对应的解压命令
# 用法:ex filename.tar.gz
ex() {
if [ -f "$1" ] ; then
case "$1" in
*.tar.bz2) tar xjf "$1" ;;
*.tar.gz) tar xzf "$1" ;;
*.bz2) bunzip2 "$1" ;;
*.rar) unrar x "$1" ;;
*.gz) gunzip "$1" ;;
*.tar) tar xf "$1" ;;
*.tbz2) tar xjf "$1" ;;
*.tgz) tar xzf "$1" ;;
*.zip) unzip "$1" ;;
*.Z) uncompress "$1" ;;
*.7z) 7z x "$1" ;;
*) echo "'$1' 无法通过 ex 解压" ;;
esac
else
echo "'$1' 不是有效的物理文件"
fi
}
# 功能:自定义快捷备份工具 (bk)
# 用法:bk <文件名|文件夹名>
bk() {
# 1. 检查是否输入了参数
if [ -z "$1" ]; then
echo "提示: 请指定要备份的文件或文件夹!"
echo "用法: bk <文件名|文件夹名>"
return 1
fi
# 2. 检查目标路径是否存在
if [ ! -e "$1" ]; then
echo "错误: 路径 '$1' 不存在,请检查输入!"
return 1
fi
# 3. 定义备份的核心路径与时间变量
local BACKUP_BASE="/backup"
local DATE_DIR=$(date +%Y-%m-%d)
local TIME_SUFFIX=$(date +%H%M%S)
local TARGET_DIR="$BACKUP_BASE/$DATE_DIR"
# 4. 自动创建目标日期的备份文件夹
if [ ! -d "$TARGET_DIR" ]; then
# 如果 /backup 目录不存在或没有权限,这里会尝试创建
mkdir -p "$TARGET_DIR" 2>/dev/null
if [ $? -ne 0 ]; then
echo "错误: 无法创建备份目录 $TARGET_DIR"
echo "原因: 当前用户对系统根目录 '/' 没有写权限。"
echo "请先在终端运行以下命令初始化 /backup 目录(仅需执行一次):"
echo " sudo mkdir -p $BACKUP_BASE && sudo chown -R \$(whoami) $BACKUP_BASE"
return 1
fi
fi
# 获取输入对象的绝对路径、纯名称以及父目录路径
local FULL_PATH=$(realpath "$1")
local BASE_NAME=$(basename "$FULL_PATH")
local DIR_NAME=$(dirname "$FULL_PATH")
# 5. 判断是文件还是文件夹,执行不同的备份逻辑
if [ -d "$FULL_PATH" ]; then
# 【文件夹逻辑】:tar压缩 -> 加时间后缀 -> 移动到目标目录
local TAR_NAME="${BASE_NAME}_${TIME_SUFFIX}.tar.gz"
echo "正在打包压缩文件夹: $BASE_NAME ..."
# -C 切换到父目录再打包,防止解压时包含绝对路径
tar -czf "$TARGET_DIR/$TAR_NAME" -C "$DIR_NAME" "$BASE_NAME"
if [ $? -eq 0 ]; then
echo "成功: 文件夹已压缩并备份至 -> $TARGET_DIR/$TAR_NAME"
# 依据需求,如果是移动文件夹,压缩成功后删除原文件夹(如不需要删除原文件夹,请注释掉下面这行)
rm -rf "$FULL_PATH"
else
echo "错误: 文件夹压缩失败!"
return 1
fi
elif [ -f "$FULL_PATH" ]; then
# 【文件逻辑】:重命名(加时间后缀) -> 移动到目标目录
local NEW_NAME=""
# 智能处理后缀名(例如:test.txt -> test_120000.txt;无后缀或隐藏文件 .bashrc -> .bashrc_120000)
if [[ "$BASE_NAME" == *.* ]] && [[ "$BASE_NAME" != .* ]]; then
local FILE_EXT="${BASE_NAME##*.}"
local FILE_NAME="${BASE_NAME%.*}"
NEW_NAME="${FILE_NAME}_${TIME_SUFFIX}.${FILE_EXT}"
else
NEW_NAME="${BASE_NAME}_${TIME_SUFFIX}"
fi
echo "正在移动并备份文件: $BASE_NAME ..."
mv "$FULL_PATH" "$TARGET_DIR/$NEW_NAME"
if [ $? -eq 0 ]; then
echo "成功: 文件已安全移动至 -> $TARGET_DIR/$NEW_NAME"
else
echo "错误: 文件移动失败!"
return 1
fi
else
echo "错误: '$BASE_NAME' 既不是普通文件也不是文件夹!"
return 1
fi
}
# 功能:将远程服务器中的内容复制到本地剪切板中
# 用法:cat t.txt | pbcopy
# 限制:iterm2中需要勾选iTerm2 → `Cmd+,` → General → Selection → Applications in terminal may access clipboard**
if [[ "$(uname)" != "Darwin" ]]; then
pbcopy() {
local buf=$(cat | base64 | tr -d '\n')
if [[ -n "$TMUX" ]]; then
printf "\ePtmux;\e\e]52;c;%s\a\e\\" "$buf"
else
printf "\e]52;c;%s\a" "$buf"
fi
}
fi
zsh配置
在MacOS上,终端默认使用zsh,zsh和bash的配置有些不一样的地方,下面是针对zsh做了适配的版本。在使用时需要先将 root 的默认 shell 改为 zsh,在普通用户下执行如下命令:
1
sudo chsh -s /bin/zsh root
输入密码后永久生效,之后再进入 root 就会默认使用 zsh。
为了让 root 加载你的 zsh 配置推荐用软链接方式,修改一次配置,普通用户和 root 两边同步生效,不用维护两份:
1
sudo ln -sf ~/.zsh_custom /var/root/.zsh_custom
上面的 .zsh_custom 是我自己创建的配置文件,无论是普通用户还是root用户默认source的配置文件都是 .zshrc,因此需要分别在他们的.zshrc(如果不存在就创建)source 这个文件,如下:
1
source ~/.zsh_custom
下面是 .zsh_custom 的配置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
# ==========================================
# 1. 基础环境与语言设置
# ==========================================
export LANG=en_US.UTF-8
export LC_ALL=en_US.UTF-8
export EDITOR='vim'
# ==========================================
# 2. Zsh 历史记录管理
# ==========================================
# 历史文件
export HISTFILE="$HOME/.zsh_history"
# 内存中保存的历史数量
export HISTSIZE=100000
# 保存到文件中的历史数量
export SAVEHIST=100000
# 实时追加历史
setopt APPEND_HISTORY
# 多终端共享历史
# 不同终端执行的命令会自动出现在其他终端中
setopt SHARE_HISTORY
# 忽略连续重复命令
setopt HIST_IGNORE_DUPS
# 删除历史中已经存在的重复命令
setopt HIST_IGNORE_ALL_DUPS
# 以空格开头的命令不保存到历史
setopt HIST_IGNORE_SPACE
# 历史记录中去掉多余空格
setopt HIST_REDUCE_BLANKS
# 保存历史时间戳
setopt EXTENDED_HISTORY
# ==========================================
# 3. 终端颜色与提示符
# ==========================================
# macOS 自带 BSD ls 使用 -G 开启颜色
alias ls='ls -G'
# GNU grep 如果通过 Homebrew 安装,则使用 ggrep 彩色输出
if command -v ggrep >/dev/null 2>&1; then
alias grep='ggrep --color=auto'
alias fgrep='gfgrep --color=auto'
alias egrep='gegrep --color=auto'
else
alias fgrep='grep -F'
alias egrep='grep -E'
fi
if [[ "$EUID" -eq 0 ]]; then
# root 用户:整体突出显示
PROMPT='%F{yellow}[%D{%Y-%m-%d %H:%M:%S}]%f %F{red}%n@%m:%2~#%f '
else
# 普通用户
PROMPT='%F{yellow}[%D{%Y-%m-%d %H:%M:%S}]%f %F{green}%n@%m%f:%F{blue}%2~%f $ '
fi
# ==========================================
# 4. 常用别名
# ==========================================
# 更直观的 ls
alias ll='ls -alF'
alias la='ls -A'
alias l='ls -CF'
# 安全保障(操作前确认)
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
# 磁盘空间
alias df='df -h'
free() {
top -l 1 | grep '^PhysMem:'
}
# 快速返回上级目录
alias ..='cd ..'
alias ...='cd ../..'
alias ....='cd ../../..'
path() {
print -rl -- $path
}
myip() {
curl -s https://ifconfig.me
echo
}
alias python='python3'
alias pip='pip3'
# ==========================================
# 5. 自定义函数
# ==========================================
mkcd() {
if [[ -z "$1" ]]; then
echo "用法: mkcd <目录名>"
return 1
fi
mkdir -p -- "$1" && cd -- "$1"
}
# ------------------------------------------
# ex
# 万能解压工具
#
# 用法:
# ex filename.tar.gz
# ------------------------------------------
ex() {
if [[ -f "$1" ]]; then
case "$1" in
*.tar.bz2) tar xjf "$1" ;;
*.tar.gz) tar xzf "$1" ;;
*.bz2) bunzip2 "$1" ;;
*.rar) unrar x "$1" ;;
*.gz) gunzip "$1" ;;
*.tar) tar xf "$1" ;;
*.tbz2) tar xjf "$1" ;;
*.tgz) tar xzf "$1" ;;
*.zip) unzip "$1" ;;
*.Z) uncompress "$1" ;;
*.7z) 7z x "$1";;
*) echo "'$1' 无法通过 ex 解压" return 1 ;;
esac
else
echo "'$1' 不是有效的物理文件"
return 1
fi
}
# ------------------------------------------
# bk
# 自定义快捷备份工具
# 用法:
# bk <文件名|文件夹名>
# 备份目录:
# /backup/YYYY-MM-DD/
# ------------------------------------------
bk() {
# 1. 检查参数
if [[ -z "$1" ]]; then
echo "提示: 请指定要备份的文件或文件夹!"
echo "用法: bk <文件名|文件夹名>"
return 1
fi
# 2. 检查目标是否存在
if [[ ! -e "$1" ]]; then
echo "错误: 路径 '$1' 不存在,请检查输入!"
return 1
fi
# 3. 备份路径与时间
local BACKUP_BASE="/backup"
local DATE_DIR
local TIME_SUFFIX
local TARGET_DIR
DATE_DIR=$(date +%Y-%m-%d)
TIME_SUFFIX=$(date +%H%M%S)
TARGET_DIR="$BACKUP_BASE/$DATE_DIR"
# 4. 创建日期目录
if [[ ! -d "$TARGET_DIR" ]]; then
mkdir -p "$TARGET_DIR" 2>/dev/null
if [[ $? -ne 0 ]]; then
echo "错误: 无法创建备份目录 $TARGET_DIR"
echo "原因: 当前用户对系统根目录 '/' 没有写权限。"
echo "请先执行:"
echo " sudo mkdir -p $BACKUP_BASE"
echo " sudo chown -R \$(whoami) $BACKUP_BASE"
return 1
fi
fi
# 5. 获取绝对路径、文件名、父目录
local FULL_PATH
local BASE_NAME
local DIR_NAME
FULL_PATH=$(realpath "$1")
BASE_NAME=$(basename "$FULL_PATH")
DIR_NAME=$(dirname "$FULL_PATH")
# 6. 文件夹逻辑
if [[ -d "$FULL_PATH" ]]; then
local TAR_NAME
TAR_NAME="${BASE_NAME}_${TIME_SUFFIX}.tar.gz"
echo "正在打包压缩文件夹: $BASE_NAME ..."
# 从父目录打包,避免出现绝对路径
tar -czf "$TARGET_DIR/$TAR_NAME" \
-C "$DIR_NAME" \
"$BASE_NAME"
if [[ $? -eq 0 ]]; then
echo "成功: 文件夹已压缩并备份至 -> $TARGET_DIR/$TAR_NAME"
# 使用 command 避免受到 rm='rm -i' 别名影响
command rm -rf "$FULL_PATH"
else
echo "错误: 文件夹压缩失败!"
return 1
fi
# 7. 文件逻辑
elif [[ -f "$FULL_PATH" ]]; then
local NEW_NAME=""
if [[ "$BASE_NAME" == *.* ]] && [[ "$BASE_NAME" != .* ]]; then
local FILE_EXT
local FILE_NAME
FILE_EXT="${BASE_NAME##*.}"
FILE_NAME="${BASE_NAME%.*}"
NEW_NAME="${FILE_NAME}_${TIME_SUFFIX}.${FILE_EXT}"
else
NEW_NAME="${BASE_NAME}_${TIME_SUFFIX}"
fi
echo "正在移动并备份文件: $BASE_NAME ..."
# command 防止受到 mv='mv -i' 别名影响
command mv "$FULL_PATH" "$TARGET_DIR/$NEW_NAME"
if [[ $? -eq 0 ]]; then
echo "成功: 文件已安全移动至 -> $TARGET_DIR/$NEW_NAME"
else
echo "错误: 文件移动失败!"
return 1
fi
else
echo "错误: '$BASE_NAME' 既不是普通文件也不是文件夹!"
return 1
fi
}