Skip to content

Latest commit

 

History

History
244 lines (176 loc) · 6.45 KB

20_OTHER.md

File metadata and controls

244 lines (176 loc) · 6.45 KB

OTHER

Использование read как альтернативы команде sleep

Удивительно, но 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

Проверить, находится ли программа в PATH пользователя

# Есть 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

Получить текущую дату с помощью strftime

В 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 V4

ВНИМАНИЕ: сгенерированное значение не защищено криптографически.

Пример функции:

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