删除重複的數組元素
建立臨時關聯數組。設定關聯數組
值并發生重複指派時,bash會覆寫該鍵。這
允許我們有效地删除數組重複。
CAVEAT:需要bash4+
示例功能:
remove_array_dups() {
# Usage: remove_array_dups "array"
declare -A tmp_array
for i in "$@"; do
[[ $i ]] && IFS=" " tmp_array["${i:- }"]=1
done
printf '%s\n' "${!tmp_array[@]}"
}
用法示例:
$ remove_array_dups 1 1 2 2 3 3 3 3 3 4 4 4 4 4 5 5 5 5 5 5
1
2
3
4
5
$ arr=(red red green blue blue)
$ remove_array_dups "${arr[@]}"
red
green
blue
随機數組元素
random_array_element() {
# Usage: random_array_element "array"
local arr=("$@")
printf '%s\n' "${arr[RANDOM % $#]}"
}
$ array=(red green blue yellow brown)
$ random_array_element "${array[@]}"
yellow
# Multiple arguments can also be passed.
$ random_array_element 1 2 3 4 5 6 7
3
循環一個數組
每次printf調用時,都會列印下一個數組元素。當
列印到達最後一個數組元素時,它
再次從第一個元素開始。
arr=(a b c d)
cycle() {
printf '%s ' "${arr[${i:=0}]}"
((i=i>=${#arr[@]}-1?0:++i))
}
在兩個值之間切換
這與上面的工作方式相同,這隻是一個不同的用例。
arr=(true false)
cycle() {
printf '%s ' "${arr[${i:=0}]}"
((i=i>=${#arr[@]}-1?0:++i))
}
LOOPS
循環一系列數字
替代seq。
# Loop from 0-100 (no variable support).
for i in {0..100}; do
printf '%s\n' "$i"
done
循環周遊可變數字範圍
# Loop from 0-VAR.
VAR=50
for ((i=0;i<=VAR;i++)); do
printf '%s\n' "$i"
done
循環數組
arr=(apples oranges tomatoes)
# Just elements.
for element in "${arr[@]}"; do
printf '%s\n' "$element"
done
循環周遊帶索引的數組
arr=(apples oranges tomatoes)
# Elements and index.
for i in "${!arr[@]}"; do
printf '%s\n' "${arr[i]}"
done
# Alternative method.
for ((i=0;i<${#arr[@]};i++)); do
printf '%s\n' "${arr[i]}"
done
循環周遊檔案的内容
while read -r line; do
printf '%s\n' "$line"
done < "file"
循環周遊檔案和目錄
不要用ls。
# Greedy example.
for file in *; do
printf '%s\n' "$file"
done
# PNG files in dir.
for file in ~/Pictures/*.png; do
printf '%s\n' "$file"
done
# Iterate over directories.
for dir in ~/Downloads/*/; do
printf '%s\n' "$dir"
done
# Brace Expansion.
for file in /path/to/parentdir/{file1,file2,subdir/file3}; do
printf '%s\n' "$file"
done
# Iterate recursively.
shopt -s globstar
for file in ~/Pictures/**/*; do
printf '%s\n' "$file"
done
shopt -u globstar
檔案處理
CAVEAT: bash在版本中不能正确處理二進制資料< 4.4。
将檔案讀取為字元串
替代cat指令。
file_data="$(<"file")"
将檔案讀取到數組(按行)
# Bash <4
IFS=#39;\n' read -d "" -ra file_data < "file"
# Bash 4+
mapfile -t file_data < "file"
擷取檔案的前N行
替代head指令。
head() {
# Usage: head "n" "file"
mapfile -tn "$1" line < "$2"
printf '%s\n' "${line[@]}"
}
$ head 2 ~/.bashrc
# Prompt
PS1='➜ '
$ head 1 ~/.bashrc
# Prompt
擷取檔案的最後N行
替代tail指令。
tail() {
# Usage: tail "n" "file"
mapfile -tn 0 line < "$2"
printf '%s\n' "${line[@]: -$1}"
}
$ tail 2 ~/.bashrc
# Enable tmux.
# [[ -z "$TMUX" ]] && exec tmux
$ tail 1 ~/.bashrc
# [[ -z "$TMUX" ]] && exec tmux
擷取檔案中的行數
替代wc -l。
示例函數(bash 4):
lines() {
# Usage: lines "file"
mapfile -tn 0 lines < "$1"
printf '%s\n' "${#lines[@]}"
}
示例函數(bash 3):
此方法使用的記憶體少于mapfile方法,并在bash3中工作,但對于較大的檔案,它的速度較慢。
lines_loop() {
# Usage: lines_loop "file"
count=0
while IFS= read -r _; do
((count++))
done < "$1"
printf '%s\n' "$count"
}
$ lines ~/.bashrc
48
$ lines_loop ~/.bashrc
48
計算目錄中的檔案或目錄
這是通過将glob的輸出傳遞給函數然後計算參數的數量來實作的。
count() {
# Usage: count /path/to/dir/*
# count /path/to/dir/*/
printf '%s\n' "$#"
}
# Count all files in dir.
$ count ~/Downloads/*
232
# Count all dirs in dir.
$ count ~/Downloads/*/
45
# Count all jpg files in dir.
$ count ~/Pictures/*.jpg
64
建立一個空檔案
替代touch。
# Shortest.
>file
# Longer alternatives:
:>file
echo -n >file
printf '' >file
提取兩個标記之間的線條
extract() {
# Usage: extract file "opening marker" "closing marker"
while IFS=#39;\n' read -r line; do
[[ $extract && $line != "$3" ]] &&
printf '%s\n' "$line"
[[ $line == "$2" ]] && extract=1
[[ $line == "$3" ]] && extract=
done < "$1"
}
# Extract code blocks from MarkDown file.
$ extract ~/projects/pure-bash/README.md '```sh' '```'
# Output here...
檔案路徑
擷取檔案路徑的目錄名稱
替代dirname指令。
dirname() {
# Usage: dirname "path"
printf '%s\n' "${1%/*}/"
}
$ dirname ~/Pictures/Wallpapers/1.jpg
/home/black/Pictures/Wallpapers/
$ dirname ~/Pictures/Downloads/
/home/black/Pictures/
擷取檔案路徑的基本名稱
替代basename指令。
basename() {
# Usage: basename "path"
: "${1%/}"
printf '%s\n' "${_##*/}"
}
$ basename ~/Pictures/Wallpapers/1.jpg
1.jpg
$ basename ~/Pictures/Downloads/
Downloads
變量
使用變量配置設定和通路變量
$ hello_world="value"
# Create the variable name.
$ var="world"
$ ref="hello_$var"
# Print the value of the variable name stored in 'hello_$var'.
$ printf '%s\n' "${!ref}"
value
或者,在bash4.3+上:
$ hello_world="value"
$ var="world"
# Declare a nameref.
$ declare -n ref=hello_$var
$ printf '%s\n' "$ref"
value
根據另一個變量命名變量
$ var="world"
$ declare "hello_$var=value"
$ printf '%s\n' "$hello_world"
value
ESCAPE序列
與流行的看法相反,使用原始逃逸序列沒有問題。使用tput與手動列印相同的ANSI序列的摘要。更糟糕的是,tput實際上并不便攜。有許多tput變體,每個變體都有不同的指令和文法(嘗試tput setaf 3使用FreeBSD系統)。原始序列很好。
文字顔色
注意:需要RGB值的序列僅适用于真彩色終端仿真器。
序列 | 它有什麼作用? | 值 |
\e[38;5;<NUM>m | 設定文本前景色。 | 0-255 |
\e[48;5;<NUM>m | 設定文本背景顔色。 | |
\e[38;2;<R>;<G>;<B>m | 将文本前景色設定為RGB顔色。 | R,G,B |
\e[48;2;<R>;<G>;<B>m | 将文本背景顔色設定為RGB顔色。 |
文字屬性
\e[m | 重置文本格式和顔色。 |
\e[1m | 粗體。 |
\e[2m | 微弱的文字。 |
\e[3m | 斜體文字。 |
\e[4m | 下劃線文字。 |
\e[5m | 慢慢眨眼。 |
\e[7m | 交換前景色和背景色。 |
光标移動
\e[<LINE>;<COLUMN>H | 将光标移動到絕對位置。 | line, column |
\e[H | 将光标移動到原位(0,0)。 | |
\e[<NUM>A | 将光标向上移動N行。 | num |
\e[<NUM>B | 将光标向下移動N行。 | |
\e[<NUM>C | 将光标向右移動N列。 | |
\e[<NUM>D | 将光标向左移動N列。 | |
\e[s | 儲存光标位置。 | |
\e[u | 恢複光标位置。 |
删除文本
\e[K | 從光标位置删除到行尾。 |
\e[1K | 從光标位置删除到行首。 |
\e[2K | 擦除整個目前行。 |
\e[J | 從目前行删除到螢幕底部。 |
\e[1J | 從目前行删除到螢幕頂部。 |
\e[2J | 清除螢幕。 |
\e[2J\e[H | 清除螢幕并将光标移動到0,0。 |
參數擴充
間接
參數 | |
${!VAR} | 根據值通路變量VAR。 |
${!VAR*} | 展開為IFS以VAR。開頭的變量名稱的分隔清單。 |
${!VAR@} | 展開為IFS以VAR。開頭的變量名稱的分隔清單。如果是雙引号,則每個變量名稱都會擴充為單獨的單詞。 |
替換
${VAR#PATTERN} | 從字元串的開頭删除模式的最短比對。 |
${VAR##PATTERN} | 從字元串的開頭删除模式的最長比對。 |
${VAR%PATTERN} | 從字元串末尾删除模式的最短比對。 |
${VAR%%PATTERN} | 從字元串末尾删除模式的最長比對。 |
${VAR/PATTERN/REPLACE} | 用字元串替換第一個比對。 |
${VAR//PATTERN/REPLACE} | 用字元串替換所有比對項。 |
${VAR/PATTERN} | 删除第一場比賽。 |
${VAR//PATTERN} | 删除所有比賽。 |
長度
${#VAR} | 字元變量的長度。 |
${#ARR[@]} | 元素中的數組長度。 |
擴張
${VAR:OFFSET} | N從變量中删除第一個字元。 | |
${VAR:OFFSET:LENGTH} | 從N字元到N字元擷取子字元串。 | |
(${VAR:10:10}:從char 10到char 擷取子字元串20) | ||
${VAR:: OFFSET} | N從變量中擷取第一個字元。 | |
${VAR:: -OFFSET} | N從變量中删除最後一個字元。 | |
${VAR: -OFFSET} | N從變量中擷取最後一個字元。 | |
${VAR:OFFSET:-OFFSET} | 削減第一個N字元和最後一個N字元。 | bash 4.2+ |
案例修改
警告 | ||
${VAR^} | 大寫第一個字元。 | bash 4+ |
${VAR^^} | 大寫所有字元。 | |
${VAR,} | 小寫第一個字元。 | |
${VAR,,} | 小寫所有字元。 |
預設值
${VAR:-STRING} | 如果VAR為空或未設定,請使用STRING其值。 |
${VAR-STRING} | 如果VAR未設定,請使用STRING其值。 |
${VAR:=STRING} | 如果VAR為空或未設定,請将值設定VAR為STRING。 |
${VAR=STRING} | 如果VAR未設定,請将值設定VAR為STRING。 |
${VAR:+STRING} | 如果VAR不為空,則使用STRING其值。 |
${VAR+STRING} | 如果VAR已設定,則使用STRING其值。 |
${VAR:?STRING} | 如果為空或未設定,則顯示錯誤。 |
${VAR?STRING} | 如果未設定則顯示錯誤。 |
BRACE EXPANSION
範圍
# Syntax: {<START>..<END>}
# Print numbers 1-100.
echo {1..100}
# Print range of floats.
echo 1.{1..9}
# Print chars a-z.
echo {a..z}
echo {A..Z}
# Nesting.
echo {A..Z}{0..9}
# Print zero-padded numbers.
# CAVEAT: bash 4+
echo {01..100}
# Change increment amount.
# Syntax: {<START>..<END>..<INCREMENT>}
# CAVEAT: bash 4+
echo {1..10..2} # Increment by 2.
字元串清單
echo {apples,oranges,pears,grapes}
# Example Usage:
# Remove dirs Movies, Music and ISOS from ~/Downloads/.
rm -rf ~/Downloads/{Movies,Music,ISOS}
有條件的表達
檔案條件
表達 | ||
-a | file | 如果檔案存在。 |
-b | 如果檔案存在并且是塊特殊檔案。 | |
-c | 如果檔案存在并且是字元特殊檔案。 | |
-d | 如果檔案存在且是目錄。 | |
-e | ||
-f | 如果檔案存在且是正常檔案。 | |
-g | 如果檔案存在且其set-group-id位已設定。 | |
-h | 如果檔案存在并且是符号連結。 | |
-k | 如果檔案存在且其粘滞位已設定 | |
-p | 如果檔案存在并且是命名管道(FIFO)。 | |
-r | 如果檔案存在且可讀。 | |
-s | 如果檔案存在且其大小大于零。 | |
-t | fd | 如果檔案描述符是打開的并且引用了終端。 |
-u | 如果檔案存在且其set-user-id位已設定。 | |
-w | 如果檔案存在且可寫。 | |
-x | 如果檔案存在且可執行。 | |
-G | 如果檔案存在且由有效組ID擁有。 | |
-L | ||
-N | 如果檔案存在且自上次讀取後已被修改。 | |
-O | 如果檔案存在并且由有效使用者ID擁有。 | |
-S | 如果檔案存在且是套接字。 |
檔案比較
file -ef file2 | 如果兩個檔案都引用相同的inode和裝置編号。 |
file -nt file2 | 如果file比file2(使用修改時間)更新或file存在file2而不存在。 |
file -ot file2 | 如果file早于file2(使用修改時間)或file2存在file而不存在。 |
可變條件
-o | opt | 如果啟用了shell選項。 |
-v | var | 如果變量具有指定的值。 |
-R | 如果variable是名稱引用。 | |
-z | 如果字元串的長度為零。 | |
-n | 如果字元串的長度不為零。 |
變量比較
var = var2 | 等于。 |
var == var2 | 等于(同義詞=)。 |
var != var2 | 不等于。 |
var < var2 | 小于(以ASCII字母順序排列。) |
var > var2 | 大于(以ASCII字母順序排列。) |
算術運算符
配置設定
營運商 | |
= | 初始化或更改變量的值。 |
算術
+ | 加成 |
- | 減法 |
* | 乘法 |
/ | 師 |
** | 幂 |
% | 模 |
+= | 加 - 等于(增加變量。) |
-= | 減去等于(減少變量。) |
*= | 時間相等(乘以變量。) |
/= | Slash-Equal(除以變量。) |
%= | Mod-Equal(除去變量的剩餘部分。) |
按位
<< | 按位左移 | |
<<= | 左移平等 | |
>> | 按位右移 | |
>>= | 右移平等 | |
& | 按位AND | |
&= | 按位AND-Equal | |
` | 按位OR | |
=` | 按位OR-等于 | |
~ | 按位NOT | |
^ | 按位異或 | |
^= | 按位XOR-Equal |
合乎邏輯
! | 不 | |
&& | 和 | |
要麼 |
雜
例 | ||
, | 逗号分隔符 | ((a=1,b=2,c=3)) |
設定變量的文法更簡單
# Simple math
((var=1+2))
# Decrement/Increment variable
((var++))
((var--))
((var+=1))
((var-=1))
# Using variables
((var=var2*arr[2]))
三元測試
# Set the value of var to var2 if var2 is greater than var.
# var: variable to set.
# var2>var: Condition to test.
# ?var2: If the test succeeds.
# :var: If the test fails.
((var=var2>var?var2:var))
TRAPS
陷阱允許腳本在各種信号上執行代碼。在pxltrm(用bash編寫的像素藝術編輯器)中,陷阱用于在視窗大小調整時重繪使用者界面。另一個用例是在腳本退出時清理臨時檔案。
應該在腳本開頭附近添加陷阱,以便捕獲任何早期錯誤。
注意:有關信号的完整清單,請參閱trap -l。
在腳本退出時做一些事情
# Clear screen on script exit.
trap 'printf \\e[2J\\e[H\\e[m' EXIT
忽略終端中斷(CTRL + C,SIGINT)
trap '' INT
對視窗調整大小做出反應
# Call a function on window resize.
trap 'code_here' SIGWINCH
在每個指令之前做點什麼
trap 'code_here' DEBUG
當shell函數或源檔案完成執行時執行某些操作
trap 'code_here' RETURN
性能
禁用Unicode
如果不需要unicode,則可以禁用它以提高性能。結果可能會有所不同,但是neofetch和其他程式有明顯改善。
# Disable unicode.
LC_ALL=C
LANG=C
已過時的文法
家當
用#!/usr/bin/env bash而不是#!/bin/bash。
- 前者搜尋使用者PATH以查找bash二進制檔案。
- 後者假設它始終安裝/bin/可能導緻問題。
# Right:
#!/usr/bin/env bash
# Wrong:
#!/bin/bash
指令替換
用$()而不是。
# Right.
var="$(command)"
# Wrong.
var=`command`
# $() can easily be nested whereas `` cannot.
var="$(command "$(command)")"
功能聲明
不要使用function關鍵字,它會降低與舊版本的相容性bash。
# Right.
do_something() {
# ...
}
# Wrong.
function do_something() {
# ...
}
内部變量
擷取bash二進制檔案的位置
"$BASH"
擷取目前正在運作的bash程序的版本
# As a string.
"$BASH_VERSION"
# As an array.
"${BASH_VERSINFO[@]}"
打開使用者首選的文本編輯器
"$EDITOR" "$file"
# NOTE: This variable may be empty, set a fallback value.
"${EDITOR:-vi}" "$file"
擷取目前函數的名稱
# Current function.
"${FUNCNAME[0]}"
# Parent function.
"${FUNCNAME[1]}"
# So on and so forth.
"${FUNCNAME[2]}"
"${FUNCNAME[3]}"
# All functions including parents.
"${FUNCNAME[@]}"
擷取系統的主機名
"$HOSTNAME"
# NOTE: This variable may be empty.
# Optionally set a fallback to the hostname command.
"${HOSTNAME:-$(hostname)}"
擷取作業系統的體系結構
"$HOSTTYPE"
擷取作業系統/核心的名稱
這可用于為不同的作業系統添加條件支援,
而無需調用uname。
"$OSTYPE"
擷取目前的工作目錄
這是pwd内置的替代品。
"$PWD"
擷取腳本運作的秒數
"$SECONDS"
擷取僞随機整數
每次$RANDOM使用時,之間的不同整數0及32767被傳回。此變量不應用于與安全性相關的任何内容(包括加密密鑰等)。
"$RANDOM"
有關終端的資訊
擷取行和列中的終端大小(來自腳本)
在純bash中編寫腳本和stty/ tput無法
調用時,這很友善。
get_term_size() {
# Usage: get_term_size
# (:;:) is a micro sleep to ensure the variables are
# exported immediately.
shopt -s checkwinsize; (:;:)
printf '%s\n' "$LINES $COLUMNS"
}
# Output: LINES COLUMNS
$ get_term_size
15 55
以像素為機關擷取終端大小
CAVEAT:這在某些終端仿真器中不起作用。
get_window_size() {
# Usage: get_window_size
printf '%b' "${TMUX:+\\ePtmux;\\e}\\e[14t${TMUX:+\\e\\\\}"
IFS=';t' read -d t -t 0.05 -sra term_size
printf '%s\n' "${term_size[1]}x${term_size[2]}"
}
# Output: WIDTHxHEIGHT
$ get_window_size
1200x800
# Output (fail):
$ get_window_size
x
擷取目前光标位置
在純bash中建立TUI時,這很有用。
get_cursor_pos() {
# Usage: get_cursor_pos
IFS='[;' read -p #39;\e[6n' -d R -rs _ y x _
printf '%s\n' "$x $y"
}
# Output: X Y
$ get_cursor_pos
1 8
轉換
将十六進制顔色轉換為RGB
hex_to_rgb() {
# Usage: hex_to_rgb "#FFFFFF"
# hex_to_rgb "000000"
: "${1/\#}"
((r=16#${_:0:2},g=16#${_:2:2},b=16#${_:4:2}))
printf '%s\n' "$r $g $b"
}
$ hex_to_rgb "#FFFFFF"
255 255 255
将RGB顔色轉換為十六進制
rgb_to_hex() {
# Usage: rgb_to_hex "r" "g" "b"
printf '#%02x%02x%02x\n' "$1" "$2" "$3"
}
$ rgb_to_hex "255" "255" "255"
#FFFFFF
CODE GOLF
更短的for循環文法
# Tiny C Style.
for((;i++<10;)){ echo "$i";}
# Undocumented method.
for i in {1..10};{ echo "$i";}
# Expansion.
for i in {1..10}; do echo "$i"; done
# C Style.
for((i=0;i<=10;i++)); do echo "$i"; done
更短的無限循環
# Normal method
while :; do echo hi; done
# Shorter
for((;;)){ echo hi;}
更短的功能聲明
# Normal method
f(){ echo hi;}
# Using a subshell
f()(echo hi)
# Using arithmetic
# This can be used to assign integer values.
# Example: f a=1
# f a++
f()(($1))
# Using tests, loops etc.
# NOTE: ‘while’, ‘until’, ‘case’, ‘(())’, ‘[[]]’ can also be used.
f()if true; then echo "$1"; fi
f()for i in "$@"; do echo "$i"; done
if文法更短
# One line
# Note: The 3rd statement may run when the 1st is true
[[ $var == hello ]] && echo hi || echo bye
[[ $var == hello ]] && { echo hi; echo there; } || echo bye
# Multi line (no else, single statement)
# Note: The exit status may not be the same as with an if statement
[[ $var == hello ]] &&
echo hi
# Multi line (no else)
[[ $var == hello ]] && {
echo hi
# ...
}
case設定變量的簡單語句
在:内置的可以用來避免重複variable=在一個case語句。該$_變量存儲的最後一個指令的最後一個參數。:總是成功,是以它可以用來存儲變量值。
# Modified snippet from Neofetch.
case "$OSTYPE" in
"darwin"*)
: "MacOS"
;;
"linux"*)
: "Linux"
;;
*"bsd"* | "dragonfly" | "bitrig")
: "BSD"
;;
"cygwin" | "msys" | "win32")
: "Windows"
;;
*)
printf '%s\n' "Unknown OS detected, aborting..." >&2
exit 1
;;
esac
# Finally, set the variable.
os="$_"
其他
使用read作為替代的sleep指令
令人驚訝的是,sleep是一個外部指令而不是bash内置指令。
read_sleep() {
# Usage: sleep 1
# sleep 0.2
read -rst "${1:-1}" -N 999
}
read_sleep 1
read_sleep 0.1
read_sleep 30
檢查程式是否在使用者的PATH中
# There are 3 ways to do this and either one can be used.
type -p executable_name &>/dev/null
hash executable_name &>/dev/null
command -v executable_name &>/dev/null
# As a test.
if type -p executable_name &>/dev/null; then
# Program is in PATH.
fi
# Inverse.
if ! type -p executable_name &>/dev/null; then
# Program is not in PATH.
fi
# Example (Exit early if program is not installed).
if ! type -p convert &>/dev/null; then
printf '%s\n' "error: convert is not installed, exiting..."
exit 1
fi
使用擷取目前日期 strftime
Bash printf有一個内置的擷取日期的方法,可用于代替date指令。
date() {
# Usage: date "format"
# See: 'man strftime' for format.
printf "%($1)T\\n" "-1"
}
# Using above function.
$ date "%a %d %b - %l:%M %p"
Fri 15 Jun - 10:00 AM
# Using printf directly.
$ printf '%(%a %d %b - %l:%M %p)T\n' "-1"
Fri 15 Jun - 10:00 AM
# Assigning a variable using printf.
$ printf -v date '%(%a %d %b - %l:%M %p)T\n' '-1'
$ printf '%s\n' "$date"
Fri 15 Jun - 10:00 AM
擷取目前使用者的使用者名
CAVEAT:需要bash4.4+
$ : \\u
# Expand the parameter as if it were a prompt string.
$ printf '%s\n' "${_@P}"
black
生成UUID V4
CAVEAT:生成的值不具有加密安全性。
uuid() {
# Usage: uuid
C="89ab"
for ((N=0;N<16;++N)); do
B="$((RANDOM%256))"
case "$N" in
6) printf '4%x' "$((B%16))" ;;
8) printf '%c%x' "${C:$RANDOM%${#C}:1}" "$((B%16))" ;;
3|5|7|9)
printf '%02x-' "$B"
;;
*)
printf '%02x' "$B"
;;
esac
done
printf '\n'
}
$ uuid
d5b6c731-1310-4c24-9fe3-55d556d44374
進度條
這是一種繪制進度條的簡單方法,無需
在函數本身中使用for循環。
bar() {
# Usage: bar 1 10
# ^----- Elapsed Percentage (0-100).
# ^-- Total length in chars.
((elapsed=$1*$2/100))
# Create the bar with spaces.
printf -v prog "%${elapsed}s"
printf -v total "%$(($2-elapsed))s"
printf '%s\r' "[${prog// /-}${total}]"
}
for ((i=0;i<=100;i++)); do
# Pure bash micro sleeps (for the example).
(:;:) && (:;:) && (:;:) && (:;:) && (:;:)
# Print the bar.
bar "$i" "10"
done
printf '\n'
擷取腳本中的函數清單
get_functions() {
# Usage: get_functions
IFS=#39;\n' read -d "" -ra functions < <(declare -F)
printf '%s\n' "${functions[@]//declare -f }"
}
繞過shell别名
# alias
ls
# command
# shellcheck disable=SC1001
\ls
繞過shell函數
# function
ls
# command
command ls
在背景運作指令
這将運作給定指令并使其保持運作,即使在終端或SSH連接配接終止後也是如此。忽略所有輸出。
bkr() {
(nohup "$@" &>/dev/null &)
}
bkr ./some_script.sh # some_script.sh is now running in the background
原文位址:https://www.cnblogs.com/lucius/p/10965638.html