Удивительно, но sleep — это внешняя команда, а не встроенная bash.
ВНИМАНИЕ: требуется bash
версии не ниже 4+
Пример фунции:
read_sleep() {
# вызов: read_sleep 1
# read_sleep 0.2
read -rt "$1" <> <(:) || :
}
Пример использования:
read_sleep 1
read_sleep 0.1
read_sleep 30
Для критичных к производительности ситуаций, когда неэкономично открывать и закрывать чрезмерное количество дескрипторов файлов, выделение файлового дескриптора может быть выполнено только один раз для всех вызовов read
:
(См. общую оригинальную реализацию на https://blog.dhampir.no/content/sleeping-without-a-subprocess-in-bash-and-how-to-sleep-forever)
exec {sleep_fd}<> <(:)
while some_quick_test; do
# эквивалент задержки 0,001
read -t 0.001 -u $sleep_fd
done
# Есть 3 способа сделать это, и любой из них можно использовать.
type -p executable_name &>/dev/null
hash executable_name &>/dev/null
command -v executable_name &>/dev/null
# в качестве теста.
if type -p executable_name &>/dev/null; then
# программа находится в PATH.
fi
# Inverse.
if ! type -p executable_name &>/dev/null; then
# программа не находится в PATH.
fi
# Пример (выйти раньше, если программа не установлена).
if ! type -p convert &>/dev/null; then
printf '%s\n' "error: convert is not installed, exiting..."
exit 1
fi
В bash printf
имеет встроенный метод получения даты, который можно использовать вместо команды date
.
ВНИМАНИЕ: требуется bash
версии не ниже 4+
Пример функции:
date() {
# вызов: date "format"
# смотрите: 'man strftime' для формата.
printf "%($1)T\\n" "-1"
}
Пример использования:
# Использование вышеуказанной функции.
$ date "%a %d %b - %l:%M %p"
Fri 15 Jun - 10:00 AM
# Использование printf напрямую.
$ printf '%(%a %d %b - %l:%M %p)T\n' "-1"
Fri 15 Jun - 10:00 AM
# Присвоение переменной с помощью printf.
$ printf -v date '%(%a %d %b - %l:%M %p)T\n' '-1'
$ printf '%s\n' "$date"
Fri 15 Jun - 10:00 AM
ВНИМАНИЕ: требуется bash версии 4.4+
$ : \\u
# Разверните параметр, как если бы это была строка приглашения.
$ printf '%s\n' "${_@P}"
black
ВНИМАНИЕ: сгенерированное значение не защищено криптографически.
Пример функции:
uuid() {
# вызов: 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() {
# вызов: bar 1 10
# ^----- истекший процент (0-100).
# ^-- общая длина в символах.
((elapsed=$1*$2/100))
# создем панель с пробелами.
printf -v prog "%${elapsed}s"
printf -v total "%$(($2-elapsed))s"
printf '%s\r' "[${prog// /-}${total}]"
}
Пример использования:
for ((i=0;i<=100;i++)); do
# чистый bash микрозадержка (для примера).
(:;:) && (:;:) && (:;:) && (:;:) && (:;:)
# вывод шкалы индикатора выполнения.
bar "$i" "10"
done
printf '\n'
get_functions() {
# вызов: get_functions
IFS=$'\n' read -d "" -ra functions < <(declare -F)
printf '%s\n' "${functions[@]//declare -f }"
}
# псевдоним
ls
# команда
# shellcheck disable=SC1001
\ls
# функция
ls
# команда
command ls
Это запустит данную команду и продолжит ее работу даже после разрыва терминала или SSH-соединения. Весь вывод игнорируется.
bkr() {
(nohup "$@" &>/dev/null &)
}
bkr ./some_script.sh # some_script.sh теперь работает в фоновом режиме
ВНИМАНИЕ: требуется bash
версии не ниже 4+
При этом используются локальные ссылки имен, чтобы избежать использования подстановки команд в стиле var=$(some_func)
для захвата выходных данных функции.
to_upper() {
local -n ptr=${1}
ptr=${ptr^^}
}
foo="bar"
to_upper foo
printf "%s\n" "${foo}" # BAR