Terminal: Das OS aliases and functions (0.9.3)
build / build (push) Successful in 23m2s

- das-shell 0.3.0: aliases and functions for every interactive bash
  (/usr/share/das/shell, loaded by /etc/bash/bashrc.d/das-aliases.sh,
  then the user's ~/.bash_aliases and ~/.bash_functions; off with
  ~/.config/das/no-aliases). Based on the author's own set, adapted to
  Void (xbps, nftables, das-update), with fixes (rmhost, netinfo,
  todo -r, dirsize, extract) and new ones (up, bigfiles, pkgowner,
  please, serve, weather, cheat, genpass, Docker shortcuts). lsfunc
  shows bilingual descriptions. Shell tests in tests/test_shell.py.
- Names that shadowed commands are gone: gh -> hgrep, mount -> mounts,
  no install or ed.
- README: "Aliases and functions" section; TODO: banner, dashboard
  service and prompt verified by the author on real hardware.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
das
2026-10-21 19:35:58 +03:00
co-authored by Claude Opus 5.5
parent 6564d1eb17
commit e01e1786d6
9 changed files with 580 additions and 12 deletions
+374
View File
@@ -0,0 +1,374 @@
# Das OS shell functions, loaded by /etc/bash/bashrc.d/das-aliases.sh in
# interactive shells. Your own ~/.bash_functions is read after this file.
# The first line of each function is its description for lsfunc:
# "# Українською | In English".
# shellcheck shell=bash
__das_uk() {
[[ ${LC_ALL:-${LC_MESSAGES:-${LANG:-}}} == uk* ]]
}
# __das_say UKRAINIAN ENGLISH
__das_say() {
if __das_uk; then echo "$1"; else echo "$2"; fi
}
# __das_usage UKRAINIAN ENGLISH: a usage line on stderr, returns 2
__das_usage() {
__das_say "використання: $1" "usage: $2" >&2
return 2
}
# __das_need COMMAND PACKAGE: is COMMAND there? If not, says which package has it
__das_need() {
command -v "$1" >/dev/null && return 0
__das_say "немає команди $1, встановіть: xi $2" "$1 is missing, install it: xi $2" >&2
return 127
}
lsfunc() {
# Список функцій з описами | List the functions with their descriptions
local name file line descr restore
restore=$(shopt -p extdebug)
shopt -s extdebug
while read -r name; do
[[ $name == _* ]] && continue
read -r _ line file < <(declare -F "$name")
descr=""
if [[ -r $file ]]; then
descr=$(sed -n "$((line + 1)),$((line + 2))p" "$file" | grep -m1 -E '^[[:space:]]*#' |
sed -E 's/^[[:space:]]*#[[:space:]]*//')
fi
if [[ $descr == *" | "* ]]; then
if __das_uk; then descr=${descr%% | *}; else descr=${descr#* | }; fi
fi
printf '%-12s %s\n' "$name" "$descr"
done < <(compgen -A function | sort)
eval "$restore"
}
# --- archives --------------------------------------------------------------------
extract() {
# Розпакувати архіви (tar.*, zip, rar, 7z, gz, xz, zst, xbps…) | Extract archives (tar.*, zip, rar, 7z, gz, xz, zst, xbps…)
(($#)) || { __das_usage "extract АРХІВ..." "extract ARCHIVE..."; return; }
local f rc=0
for f in "$@"; do
if [[ ! -f $f ]]; then
__das_say "'$f' — не файл" "'$f' is not a file" >&2
rc=1
continue
fi
case ${f,,} in
*.tar | *.tar.* | *.tgz | *.tbz | *.tbz2 | *.txz | *.tzst | *.xbps) tar -xvf "$f" ;;
*.zip | *.jar) __das_need unzip unzip && unzip "$f" ;;
*.rar) __das_need unrar unrar && unrar x "$f" ;;
*.7z) __das_need 7z 7zip && 7z x "$f" ;;
*.gz) gunzip -k "$f" ;;
*.bz2) bunzip2 -k "$f" ;;
*.xz) unxz -k "$f" ;;
*.zst) __das_need unzstd zstd && unzstd "$f" ;;
*.lz4) __das_need lz4 lz4 && lz4 -d "$f" ;;
*.z) uncompress "$f" ;;
*)
__das_say "'$f': невідомий тип архіву" "'$f': unknown archive type" >&2
false
;;
esac || rc=1
done
return $rc
}
compress() {
# Запакувати файли в архів; тип за назвою | Pack files into an archive, the type comes from the name
(($# >= 2)) || { __das_usage "compress АРХІВ.tar.gz ФАЙЛ..." "compress ARCHIVE.tar.gz FILE..."; return; }
local archive=$1
shift
case ${archive,,} in
*.tar.gz | *.tgz) tar -czvf "$archive" -- "$@" ;;
*.tar.bz2 | *.tbz2) tar -cjvf "$archive" -- "$@" ;;
*.tar.xz | *.txz) tar -cJvf "$archive" -- "$@" ;;
*.tar.zst | *.tzst) __das_need zstd zstd && tar --zstd -cvf "$archive" -- "$@" ;;
*.tar) tar -cvf "$archive" -- "$@" ;;
*.zip) __das_need zip zip && zip -r "$archive" -- "$@" ;;
*.7z) __das_need 7z 7zip && 7z a "$archive" -- "$@" ;;
*)
__das_say "невідомий тип архіву: $archive (tar.gz, tar.xz, tar.zst, zip, 7z…)" \
"unknown archive type: $archive (tar.gz, tar.xz, tar.zst, zip, 7z…)" >&2
return 1
;;
esac
}
bu() {
# Резервна копія файлу з датою в назві | Back up a file with the date in its name
(($#)) || { __das_usage "bu ФАЙЛ..." "bu FILE..."; return; }
local f stamp
stamp=$(date +%Y%m%d%H%M%S)
for f in "$@"; do
cp -a -- "$f" "$f-$stamp.backup" && echo "$f-$stamp.backup"
done
}
# --- directories and files -----------------------------------------------------------
mkcd() {
# Створити каталог і перейти в нього | Make a directory and go into it
(($# == 1)) || { __das_usage "mkcd КАТАЛОГ" "mkcd DIR"; return; }
mkdir -p -- "$1" && cd -- "$1" || return
}
cl() {
# Перейти в каталог і показати його вміст | Change to a directory and list it
cd -- "${1:-$HOME}" && ls
}
up() {
# Піднятися на N каталогів вгору | Go N directories up
local n=${1:-1} dir=""
[[ $n =~ ^[0-9]+$ ]] || { __das_usage "up [N]" "up [N]"; return; }
while ((n-- > 0)); do dir+="../"; done
cd -- "${dir:-.}" || return
}
f() {
# Знайти файли за назвою (шаблон, без регістру) | Find files by name (a pattern, any case)
(($#)) || { __das_usage "f ШАБЛОН [КАТАЛОГ]" "f PATTERN [DIR]"; return; }
local pattern=$1
[[ $pattern == *[*?[]* ]] || pattern="*$pattern*"
find "${2:-.}" -iname "$pattern" 2>/dev/null
}
dirsize() {
# Розміри всього в каталозі, за зростанням | Sizes of everything in a directory, smallest first
local dir=${1:-.}
du -shx -- "$dir"/* "$dir"/.[!.]* 2>/dev/null | sort -h
}
whatsize() {
# Розміри підкаталогів (типово /) на тій самій ФС, за спаданням | Subdirectory sizes (/ by default) on the same filesystem, largest first
du -hx --max-depth=1 -- "${1:-/}" 2>/dev/null | sort -hr
}
bigfiles() {
# N найбільших файлів у каталозі | The N largest files in a directory
find "${1:-.}" -xdev -type f -printf '%s\t%p\n' 2>/dev/null | sort -nr | head -n "${2:-10}" |
numfmt --to=iec --field=1
}
ednt() {
# Редагувати файл, не змінюючи часу зміни | Edit a file keeping its modification time
(($# == 1)) || { __das_usage "ednt ФАЙЛ" "ednt FILE"; return; }
local mtime
mtime=$(stat -c %y -- "$1") || return
"${VISUAL:-${EDITOR:-vi}}" "$1"
touch -d "$mtime" -- "$1"
}
devid() {
# Пристрої: lsblk, blkid і lsusb разом | Devices: lsblk, blkid and lsusb at once
echo '--- lsblk ---'
lsblk -f -e 7
echo '--- blkid ---'
sudo blkid | grep -v '^/dev/loop'
echo '--- lsusb ---'
lsusb
}
# --- processes and history -------------------------------------------------------------
psa() {
# Процеси, в рядку яких є текст | Processes whose line contains the text
(($#)) || { __das_usage "psa ТЕКСТ" "psa TEXT"; return; }
ps aux | awk -v p="$1" 'NR == 1 || (tolower($0) ~ tolower(p) && !/awk -v p=/)'
}
pst() {
# Те саме деревом процесів | The same as a process tree
(($#)) || { __das_usage "pst ТЕКСТ" "pst TEXT"; return; }
# shellcheck disable=SC2009 # pgrep has no tree
ps auxf | grep -i -B 10 -A 5 -- "$1" | grep -v -e 'grep -i -B' -e 'ps auxf'
}
histat() {
# N найчастіших команд з історії | The N most used commands from history
history | awk -v n="${1:-10}" '
{ sub(/^ *[0-9]+\*? +/, ""); split($0, w, " "); c = w[1]; if (c != "") { cnt[c]++; total++ } }
END { for (c in cnt) printf "%d\t%.1f%%\t%s\n", cnt[c], cnt[c] * 100 / total, c }' |
sort -nr | head -n "${1:-10}" | nl
}
EC() {
# Код завершення попередньої команди | The previous command's exit code
local code=$?
printf '\e[1;33mcode %d\e[m\n' "$code"
return "$code"
}
please() {
# Повторити попередню команду через sudo | Run the previous command again with sudo
local cmd
cmd=$(fc -ln -1)
cmd=${cmd#"${cmd%%[![:space:]]*}"}
echo "sudo $cmd" >&2
sudo bash -c "$cmd"
}
# --- packages (xbps) --------------------------------------------------------------------
pkgshow() {
# Встановлені пакети, з фільтром за назвою | Installed packages, filtered by name
xbps-query -l | awk '{print $2}' | grep -i -- "${1:-.}" | sort
}
pkgfind() {
# Шукати пакети в репозиторіях | Search the repositories for packages
(($#)) || { __das_usage "pkgfind ТЕКСТ" "pkgfind TEXT"; return; }
xbps-query -Rs "$1"
}
pkgowner() {
# Якому пакету належить файл чи команда | Which package owns a file or a command
(($#)) || { __das_usage "pkgowner ФАЙЛ|КОМАНДА" "pkgowner FILE|COMMAND"; return; }
local path=$1
[[ $path == */* ]] || path=$(type -P -- "$1") || path=$1
xbps-query -o "$(readlink -f -- "$path")"
}
# --- network -----------------------------------------------------------------------------
myip() {
# Зовнішня IP-адреса | The public IP address
curl -fsS --max-time 5 https://ifconfig.me/ip && echo
}
netinfo() {
# Адреси, шлюз, DNS і зовнішня IP | Addresses, gateway, DNS and the public IP
echo "--- $(__das_say "Адреси" "Addresses") ---"
command ip -br address | grep -v '^lo '
echo "--- $(__das_say "Шлюз" "Gateway") ---"
command ip route show default
echo "--- DNS ---"
awk '/^nameserver/ {print $2}' /etc/resolv.conf
echo "--- $(__das_say "Зовнішня IP" "Public IP") ---"
myip
}
listen() {
# Слухати порт TCP і показувати, що прийшло | Listen on a TCP port and print what arrives
(($# == 1)) || { __das_usage "listen ПОРТ" "listen PORT"; return; }
__das_need nc openbsd-netcat || return
nc -lvn "$1"
}
rmhost() {
# Прибрати хост або рядок N з ~/.ssh/known_hosts | Remove a host or line N from ~/.ssh/known_hosts
(($# == 1)) || { __das_usage "rmhost ХОСТ|НОМЕР_РЯДКА" "rmhost HOST|LINE_NUMBER"; return; }
if [[ $1 =~ ^[0-9]+$ ]]; then
sed -i.bak "${1}d" ~/.ssh/known_hosts && echo "$HOME/.ssh/known_hosts.bak"
else
ssh-keygen -R "$1"
fi
}
serve() {
# Роздати поточний каталог по HTTP (типово порт 8000) | Serve the current directory over HTTP (port 8000 by default)
__das_need python3 python3 || return
python3 -m http.server "${1:-8000}"
}
weather() {
# Погода з wttr.in (місто з аргументу або за IP) | Weather from wttr.in (the city given, or by IP)
local lang=en
__das_uk && lang=uk
curl -fsS --max-time 10 "https://wttr.in/${1// /+}?lang=$lang"
}
cheat() {
# Шпаргалка до команди з cheat.sh | A command's cheat sheet from cheat.sh
(($#)) || { __das_usage "cheat КОМАНДА" "cheat COMMAND"; return; }
curl -fsS --max-time 10 "https://cheat.sh/$1"
}
# --- small tools -------------------------------------------------------------------------
calc() {
# Порахувати вираз | Calculate an expression
(($#)) || { __das_usage "calc ВИРАЗ" "calc EXPRESSION"; return; }
if command -v bc >/dev/null; then
echo "scale=3; $*" | bc -l
else
awk "BEGIN { print $* }"
fi
}
epoch() {
# Поточний час Unix або перетворити його на дату | The current Unix time, or turn one into a date
if (($#)); then
date -d "@$1" -R
else
date +%s
fi
}
genpass() {
# Випадковий пароль (типово 20 символів) | A random password (20 characters by default)
local n=${1:-20}
[[ $n =~ ^[0-9]+$ ]] || { __das_usage "genpass [ДОВЖИНА]" "genpass [LENGTH]"; return; }
LC_ALL=C tr -dc 'A-Za-z0-9_@%+=.,-' </dev/urandom | head -c "$n"
echo
}
csrc() {
# Скомпілювати й запустити програму на C | Compile and run a C source file
(($#)) || { __das_usage "csrc ФАЙЛ.c [АРГУМЕНТИ]" "csrc FILE.c [ARGS]"; return; }
[[ -r $1 ]] || { __das_say "немає файлу $1" "no such file: $1" >&2; return 1; }
__das_need gcc gcc || return
local src=$1 bin rc
shift
bin=$(mktemp) || return
gcc "$src" -o "$bin" && "$bin" "$@"
rc=$?
rm -f -- "$bin"
return $rc
}
note() {
# Нотатки в ~/.notes: без аргументів показати, -c очистити | Notes in ~/.notes: no arguments shows them, -c clears
local file=$HOME/.notes
if ! (($#)); then
[[ -f $file ]] && cat -- "$file"
elif [[ $1 == -c ]]; then
: >"$file"
else
printf '%s\n' "$*" >>"$file"
fi
}
todo() {
# Справи в ~/.todo: -l з номерами, -r N виконано, -c очистити | To-dos in ~/.todo: -l numbered, -r N done, -c clears
local file=$HOME/.todo
case ${1:-} in
"") [[ -f $file ]] && cat -- "$file" ;;
-l) [[ -f $file ]] && nl -b a -- "$file" ;;
-c) : >"$file" ;;
-r)
local n=${2:-}
if [[ -z $n ]]; then
nl -b a -- "$file"
read -r -p "$(__das_say "Номер, що прибрати: " "Number to remove: ")" n
fi
[[ $n =~ ^[0-9]+$ ]] || return 1
sed -i "${n}d" -- "$file"
;;
*) printf '%s\n' "$*" >>"$file" ;;
esac
}
man() {
# man з кольоровими заголовками | man with coloured headings
LESS_TERMCAP_mb=$'\e[1;31m' LESS_TERMCAP_md=$'\e[1;31m' LESS_TERMCAP_me=$'\e[0m' \
LESS_TERMCAP_so=$'\e[1;44;33m' LESS_TERMCAP_se=$'\e[0m' \
LESS_TERMCAP_us=$'\e[1;32m' LESS_TERMCAP_ue=$'\e[0m' \
GROFF_NO_SGR=1 command man "$@"
}