Чист .bashrc: alias-и в отделен файл и готови функции
Как разделих разхвърляния си .bashrc на две – настройки и функции в един файл, alias-и в друг (~/.fedya_aliases) – и какво точно да добавите в .bashrc, за да чете втория. Пълен код и обяснение за всеки alias и функция.
С времето моят ~/.bashrc се превърна в смесица от всичко: настройки на history, промпт, функции и над петдесет alias-а, наредени в реда, в който съм ги добавял. Всеки път, когато трябваше да променя една малка команда, ровех из файл, в който нищо не беше на мястото си.
Затова го подредих и го разделих на две:
| Файл | Какво съдържа |
|---|---|
~/.bashrc |
Настройки на Bash (history, промпт, цветове), външни инструменти (keychain, Starship, NVM) и функции |
~/.fedya_aliases |
Alias-и, подредени в 11 тематични секции, и две помощни функции за преглед и търсене в тях (aliases, fa) |
В .bashrc остава един малък блок, който зарежда втория файл. Така alias-ите ми са на едно място, лесно ги архивирам, а ако някой от вас иска да ги вземе като идея, му давам един файл, а не целия си .bashrc.
В статията ще намерите:
- Какво точно да добавите в
.bashrc, за да чете другия файл. - Пълния код на
~/.fedya_aliasesс обяснение на всяка секция. - Пълния код на
~/.bashrcс обяснение на настройките и функциите и как се работи с тях. - Как да приложите всичко при себе си, без да рискувате да останете с неработещ терминал.
Най-важното: как .bashrc чете файла с alias-и
Ето блокът, който стои в самия край на моя .bashrc:
# ЗАРЕЖДАНЕ НА ЛИЧНИТЕ ALIASES
if [ -f ~/.fedya_aliases ]; then
. ~/.fedya_aliases
fi
Какво прави той:
[ -f ~/.fedya_aliases ]проверява дали файлът съществува. Ако го няма,.bashrcпросто продължава и не показва грешка..(същото катоsource) изпълнява файла в текущата сесия. Само така alias-ите остават налични в терминала. Ако файлът се стартира като отделен скрипт, alias-ите изчезват заедно с него.- Блокът е най-накрая, за да има файлът с alias-и последната дума. Ако в
.bashrcе дефиниран alias със същото име, по-късната дефиниция печели.
Добавяне с една команда
Ако не искате да отваряте редактор, добавете блока директно:
cat >> ~/.bashrc <<'EOF'
# ЗАРЕЖДАНЕ НА ЛИЧНИТЕ ALIASES
if [ -f ~/.fedya_aliases ]; then
. ~/.fedya_aliases
fi
EOF
Забележете двойното >> – то добавя в края на файла. Единично > би го презаписало.
Презареждане и проверка
Промените в .bashrc влизат в сила в нов терминал. В отворен терминал ги заредете така:
source ~/.bashrc
Проверете, че alias-ите са налични:
type ll # ll is aliased to `ls -alF'
alias ll # същото, в форма, която можете да копирате
aliases # всички alias-и, оцветени и подредени
aliases docker # само тези, които съдържат "docker"
fa # интерактивно търсене в alias-и и функции
Внимание при преминаване от стар
.bashrc. Ако в отворения терминал още е зареден стар alias със същото име като функция от новия файл (при мен това еaliases), alias-ът има предимство пред функцията. Отворете нов терминал или първо изпълнетеunalias aliases.
Още няколко правила, които е полезно да знаете
- Debian и Ubuntu вече имат такъв механизъм. Стандартният
.bashrcтам зарежда файла~/.bash_aliases, ако съществува. Ако не сте изтрили този блок, е достатъчно да кръстите файла.bash_aliasesи не се налага да добавяте нищо. Аз избрах собствено име, за да е ясно кой е моят. - Alias-ите работят само в интерактивен терминал. В скриптовете Bash не ги разгъва по подразбиране. Ако командата ви трябва и в скрипт, направете я функция или скрипт.
- Проверка на синтаксиса преди да отворите нов терминал:
bash -n ~/.fedya_aliases(не изпълнява нищо, само търси синтактични грешки). Ако всичко е наред, командата не връща изход. - Как да заобиколя alias за един път:
\lsилиcommand lsизпълняват оригиналната команда. Премахване на alias за текущата сесия:unalias име.
Файл 1: ~/.fedya_aliases
Ето пълното съдържание на файла. Alias-ите са в 11 секции с еднакъв формат: коментар, а под него самата команда.
# =================================================================
# FEDYA ALIASES
# =================================================================
# Всички лични Bash alias-и
#
# Подредени по предназначение:
# 01. System / Navigation
# 02. Files / Search
# 03. Network
# 04. Docker
# 05. Proxmox / Ansible / Backup
# 06. Git / Development
# 07. Node / NPM / Astro
# 08. Terminal / Bash
# 09. Directories / Projects
# 10. SSH / Security
# 11. Notifications
#
# Преглед и търсене:
# aliases [дума] (или myaliases) – списък на alias-и; с дума – търсене
# fa – интерактивно търсене (fzf) в alias-и и функции
# =================================================================
# =================================================================
# 01. SYSTEM / NAVIGATION
# =================================================================
# Изчистване на терминала
alias c='clear'
# Една / две директории нагоре
alias ..='cd ..'
alias ...='cd ../..'
# Преглед на PATH — по един елемент на ред
alias path='echo -e ${PATH//:/\\n}'
# Преглед на Bash history
alias h='history'
# Системен update
alias update='sudo apt update && sudo apt upgrade -y'
# Рестарт
alias reboot='sudo shutdown -r now'
# Преглед и търсене на alias-и и функции
# aliases – всички alias-и, оцветени и по азбучен ред
# aliases docker – alias-и (по име или команда) и функции (по име), съдържащи "docker"
# (функция, защото при alias кавичките в awk/sed стават неудобни)
aliases() {
local q="${1,,}" name value found=0
for name in $(printf '%s\n' "${!BASH_ALIASES[@]}" | sort); do
value=${BASH_ALIASES[$name]}
value=${value//\\$'\n'/} # маха "\" + нов ред (многоредови alias-и)
value=${value//$'\n'/ } # останалите нови редове -> интервал
while [[ $value == *" "* ]]; do value=${value// / }; done
if [[ -z $q || ${name,,} == *"$q"* || ${value,,} == *"$q"* ]]; then
printf '\033[1;36m%-14s\033[0m \033[1;33m%s\033[0m\n' "$name" "$value"
found=1
fi
done
if [[ -n $q ]]; then
for name in $(declare -F | awk '{print $3}' | grep -v '^_' | sort); do
if [[ ${name,,} == *"$q"* ]]; then
printf '\033[1;35m%-14s\033[0m (функция) виж: type %s\n' "$name" "$name"
found=1
fi
done
(( found )) || echo "Няма съвпадения за: $1"
fi
}
alias myaliases='aliases'
# Търсене на alias-и [A] и функции [F] – по име, команда или описание
# Enter извежда дефиницията. Ползване: fa
fa() {
local -A desc
local name value sel
# Описанието е първият коментар над дефиницията
while IFS=$'\t' read -r name value; do
desc[$name]=$value
done < <(awk '
/^[[:space:]]*$/ { c = ""; inrun = 0; next }
/^#/ {
if ($0 ~ /^# ?=/) { c = ""; inrun = 1; next }
if (!inrun) c = substr($0, 3)
inrun = 1
next
}
{ inrun = 0 }
/^alias [^=]+=/ {
n = $2
sub(/=.*/, "", n)
if (c != "") print n "\t" c
next
}
/^[A-Za-z_][A-Za-z0-9_]*\(\) *\{/ {
n = $1
sub(/\(\).*/, "", n)
if (c != "") print n "\t" c
c = ""
next
}
' ~/.bashrc ~/.fedya_aliases)
sel=$(
{
# Alias-и
for name in $(compgen -A alias | sort); do
value=${BASH_ALIASES[$name]}
value=${value//\\$'\n'/}
value=${value//$'\n'/ }
while [[ $value == *" "* ]]; do
value=${value// / }
done
printf '[A] %-12s %s' "$name" "$value"
[[ -n ${desc[$name]} ]] && printf ' # %s' "${desc[$name]}"
printf '\n'
done
# Functions
for name in $(compgen -A function | grep -Ev '^(_|nvm|starship)' | sort); do
printf '[F] %-12s' "$name"
[[ -n ${desc[$name]} ]] && printf ' # %s' "${desc[$name]}"
printf '\n'
done
} | fzf "$@"
) || return
[[ -z $sel ]] && return
# Извлича името независимо дали е [A] или [F]
name=$(printf '%s\n' "$sel" | head -1 | sed -E 's/^\[[AF]\] +([^ ]+).*/\1/')
echo
type "$name"
}
# =================================================================
# 02. FILES / LS / SEARCH
# =================================================================
# Цветен ls
alias ls='ls --color=auto'
# Основни варианти на ls
alias l='ls -CF'
alias la='ls -A'
alias ll='ls -alF'
# Оцветен grep
alias grep='grep --color=auto'
alias fgrep='fgrep --color=auto'
alias egrep='egrep --color=auto'
# Disk usage
alias dfh='df -h'
alias duh='du -sh *'
# Цветен преглед на текстови файлове (Изисква: pygmentize)
alias cats='pygmentize -g'
# Дървовидна структура
alias tree='find . -print | sed -e '\''s;[^/]*/;|____;g;s;____|; |;g'\'''
# Следене на лог
alias tf='tail -f'
# Специализиран скрипт
alias las='cat /usr/local/sbin/as'
# =================================================================
# 03. NETWORK
# =================================================================
# Показва публичния IP адрес
alias cip='curl icanhazip.com'
# Ping към Google DNS
alias pingg='ping 8.8.8.8'
# =================================================================
# 04. DOCKER
# =================================================================
# Кратък Docker alias
alias d='docker'
# Docker Compose
alias dcd='docker compose down'
alias dcu='docker compose up -d'
# Работещи контейнери — компактен изглед
alias dps='docker ps --format "table {{.ID}}\t{{.Names}}\t{{.Status}}\t{{.Image}}\t{{.Ports}}"'
# Всички Docker images
alias dimg='docker images'
# Следене на container logs
alias dlf='docker logs -f'
# Същото като dlf — запазено за обратна съвместимост
alias dlog='docker logs -f'
# Изтриване на всички спрени containers
alias drm='docker rm $(docker ps -a -q)'
# Изтриване на всички images
alias drmi='docker rmi $(docker images -q)'
# Спиране на всички работещи containers
alias dstop='docker stop $(docker ps -q)'
# ctop — Docker container monitoring
alias ctop='docker run --rm -ti \
--name=ctop \
-v /var/run/docker.sock:/var/run/docker.sock \
quay.io/vektorlab/ctop:latest'
# =================================================================
# 05. PROXMOX / ANSIBLE / BACKUPS
# =================================================================
# SSH към Proxmox host
alias prox='ssh prox'
# Backup на CT 114
alias backups_wp='backup_ct 114'
# Списък на Proxmox backup файловете
alias list_backups='ls -lah /mnt/d/backup_proxmox/'
# Ansible — добавяне на SSH key
alias key='ansible-playbook \
/home/fedia/ansible/add-key.yaml \
-i /home/fedia/ansible/servers.ini'
# =================================================================
# 06. GIT / DEVELOPMENT
# =================================================================
# Git помощен файл
alias githelp='cat /home/fedia/github_ssh_setup.txt'
# Git помощно меню
alias gitmenu='/home/fedia/githelp_menu.sh'
# =================================================================
# 07. NODE / NPM / ASTRO
# =================================================================
# Стартиране на development server
alias dev='npm run dev'
# Build (поддържаме и двата варианта за удобство)
alias build='npm run build'
alias bild='npm run build'
# =================================================================
# 08. TERMINAL / BASH
# =================================================================
# Преглед на .bashrc
alias brc='cat ~/.bashrc'
# Показване на command database
alias cmdlist='grep -v "^#" ~/.commands.txt |
grep -v "^$" |
column -t -s "||"'
# Редактиране на command database
alias cmdedit='nano ~/.commands.txt'
# Добавяне на команда в database
alias cmdadd='_cmdadd() {
echo "$1 || $2 || $3" >> ~/.commands.txt &&
echo "✓ Добавено: $1"
}; _cmdadd'
# =================================================================
# 09. DIRECTORIES / PROJECTS
# =================================================================
# Windows Desktop
alias desktop='cd /mnt/c/Users/fedia/Desktop'
# Защита от грешно изписване на desktop
alias dekstop='cd /mnt/c/Users/fedia/Desktop'
# Nextcloud
alias nex='cd /mnt/c/Users/fedia/Nextcloud'
# Здраве & Красота
alias zdrave='cd /mnt/c/Users/fedia/Desktop/zdravemag'
# Train Brakes
alias vlak='cd /mnt/c/Users/fedia/Desktop/trainbrakes'
# LinuxDev / DevOps
alias devops='cd /mnt/c/Users/fedia/Desktop/linux-devops'
# FS проект
alias fs='cd /mnt/c/Users/fedia/Desktop/fs'
# =================================================================
# 10. SSH / SECURITY
# =================================================================
# SSH без проверка на host key
alias sship='ssh \
-o StrictHostKeyChecking=no \
-o UserKnownHostsFile=/dev/null \
-o LogLevel=ERROR'
# =================================================================
# 11. NOTIFICATIONS
# =================================================================
# Известие след приключване на дълга команда
alias alert='notify-send --urgency=low \
-i "$([ $? = 0 ] && echo terminal || echo error)" \
"$(history | tail -n1 |
sed -e '\''s/^\s*[0-9]\+\s*//;
s/[;&|]\s*alert$//'\'')"'
# =================================================================
# END OF FEDYA ALIASES
# =================================================================
01. System / Navigation
| Alias | Какво прави |
|---|---|
c |
clear – изчиства терминала |
.. и ... |
Една и две директории нагоре |
path |
Показва $PATH по един елемент на ред |
h |
Кратко за history |
update |
sudo apt update && sudo apt upgrade -y – обновява системата с една дума |
reboot |
sudo shutdown -r now. В WSL не рестартира Windows хоста; дистрибуцията се рестартира от Windows с wsl --terminate или wsl --shutdown |
aliases, myaliases |
Показват всички alias-и, оцветени и по азбучен ред. С дума след тях (aliases docker) търсят |
fa |
Интерактивно търсене с fzf в alias-и и функции – по име, команда или описание (виж раздела „Как да намеря забравен alias или функция“) |
aliases и fa са единствените неща в този файл, които не са alias-и, а функции, дефинирани директно. Причината е, че многоредовите alias-и и кавичките в sed и awk бързо стават нечетими вътре в единични кавички, а функцията се чете и поправя лесно.
aliases работи така:
aliases() {
local q="${1,,}" name value found=0
for name in $(printf '%s\n' "${!BASH_ALIASES[@]}" | sort); do
value=${BASH_ALIASES[$name]}
value=${value//\\$'\n'/} # маха "\" + нов ред (многоредови alias-и)
value=${value//$'\n'/ } # останалите нови редове -> интервал
while [[ $value == *" "* ]]; do value=${value// / }; done
if [[ -z $q || ${name,,} == *"$q"* || ${value,,} == *"$q"* ]]; then
printf '\033[1;36m%-14s\033[0m \033[1;33m%s\033[0m\n' "$name" "$value"
found=1
fi
done
if [[ -n $q ]]; then
for name in $(declare -F | awk '{print $3}' | grep -v '^_' | sort); do
if [[ ${name,,} == *"$q"* ]]; then
printf '\033[1;35m%-14s\033[0m (функция) виж: type %s\n' "$name" "$name"
found=1
fi
done
(( found )) || echo "Няма съвпадения за: $1"
fi
}
BASH_ALIASESе вграден в Bash масив с всички дефинирани в момента alias-и. Ключът е името, стойността е командата.${1,,}превръща думата за търсене в малки букви (Bash 4+), а${name,,}прави същото за имената, така че търсенето не различава главни и малки букви.- Alias се показва, ако думата е в името или в командата му. Без дума се показват всички.
- Функциите се изброяват с
declare -F, аgrep -v '^_'пропуска вътрешните (тези на bash-completion). Те се търсят само по име и се показват в пурпурно с подсказкаtype име. - Двата реда с
${value//…/…}слепват многоредовите alias-и (катоctopиkey) в един ред. printfпечата името в циан и командата в жълто.
Пример за употреба:
aliases # всички alias-и
aliases docker # само тези с "docker" в името или в командата
aliases | less -R # прелистване, като -R запазва цветовете
02. Files / LS / Search
| Alias | Какво прави |
|---|---|
ls |
ls --color=auto – цветен изход |
l, la, ll |
Компактен списък; всички файлове без . и ..; подробен списък със скритите файлове |
grep, fgrep, egrep |
Същите команди с цветно оцветяване на съвпаденията |
dfh |
df -h – свободно място на дисковете |
duh |
du -sh * – размер на всичко в текущата директория. Не включва скритите файлове (тези с точка) |
cats |
Оцветен преглед на файл (cats файл.py). Изисква pygmentize |
tree |
Дървовидна структура на директорията с find и sed. Заменя истинската команда tree, ако е инсталирана |
tf |
tail -f – следене на лог (tf /var/log/syslog) |
las |
Показва съдържанието на моя собствен скрипт /usr/local/sbin/as |
pygmentize идва с пакета python3-pygments (sudo apt install python3-pygments).
03. Network
| Alias | Какво прави |
|---|---|
cip |
curl icanhazip.com – показва публичния ви IP адрес |
pingg |
ping 8.8.8.8 – бърза проверка дали има интернет. Работи безкрайно, спира с Ctrl+C |
04. Docker
| Alias | Какво прави |
|---|---|
d |
Кратко за docker |
dcu / dcd |
docker compose up -d / docker compose down |
dps |
docker ps в компактна таблица: ID, име, статус, image, портове |
dimg |
docker images |
dlf, dlog |
docker logs -f – следене на лога на контейнер (dlf име). dlog е същото, останало от по-стар вариант |
drm |
Изтрива всички спрени контейнери |
drmi |
Опитва да изтрие всички images |
dstop |
Спира всички работещи контейнери |
ctop |
Стартира ctop (мониторинг на контейнерите) като временен контейнер |
Пример:
dcu # стартира проекта от docker-compose.yml
dps # виждам какво работи
dlf my_container # следя лога
dcd # спирам и махам контейнерите на проекта
⚠️ Внимавайте с
drm,drmiиdstop. Те действат върху всичко на машината, а не само върху текущия проект, и не питат за потвърждение.drmне може да изтрие работещи контейнери (Docker го отказва без-f), ноdrmiще изтрие всеки image, който не се ползва от контейнер (дори спрян), и после ще ги теглите отново. Ако искате по-безопасен вариант, вграденитеdocker container pruneиdocker image pruneпитат за потвърждение.
ctop работи така: --rm изтрива временния контейнер след излизане, -ti дава интерактивен терминал, а -v /var/run/docker.sock:… му позволява да чете състоянието на Docker. Първото стартиране тегли image-а.
05. Proxmox / Ansible / Backups
| Alias | Какво прави |
|---|---|
prox |
ssh prox – връзка към Proxmox сървъра. Изисква запис Host prox в ~/.ssh/config |
backups_wp |
backup_ct 114 – теглене на най-новия бекъп на контейнер 114 (функцията е описана по-долу) |
list_backups |
Списък на свалените бекъпи в /mnt/d/backup_proxmox/ |
key |
Пуска Ansible playbook, който добавя моя SSH ключ на сървърите от servers.ini |
06. Git / Development
| Alias | Какво прави |
|---|---|
githelp |
Показва бележките ми как се настройва SSH достъп до GitHub |
gitmenu |
Пуска помощното ми меню за Git (githelp_menu.sh) |
07. Node / NPM / Astro
| Alias | Какво прави |
|---|---|
dev |
npm run dev – development сървър |
build, bild |
npm run build. Втората форма е защита от моя често срещана печатна грешка |
08. Terminal / Bash
| Alias | Какво прави |
|---|---|
brc |
Показва .bashrc |
cmdlist |
Показва базата ми с команди като подредена таблица |
cmdedit |
Отваря базата в nano |
cmdadd |
Добавя нова команда в базата |
Базата е обикновен текстов файл ~/.commands.txt. Всеки ред има три части, разделени с ||:
Описание || тагове || команда
Ето пример (файлът ~/.commands.txt се създава автоматично при първото добавяне):
cmdadd "Свободно място" "disk,df" "df -h"
cmdadd "Следене на лог" "log,tail" "tail -f /var/log/syslog"
cmdlist
Резултатът от cmdlist е подредена таблица с трите колони. Ако командата или описанието са с интервали, ги слагайте в кавички, както е по-горе. Търсенето в базата с fzf е във функцията cmd, която е описана по-долу.
cmdadd е alias, който вътре дефинира функция и веднага я вика. Това е заобикаляне на ограничението, че alias не може да ползва аргументите като $1, $2. По-чисто решение е обикновена функция в .bashrc, но този вариант работи и остава в един файл с останалите.
09. Directories / Projects
| Alias | Накъде води |
|---|---|
desktop, dekstop |
Windows Desktop. Втората форма е защита от печатна грешка |
nex |
Папката на Nextcloud |
zdrave, vlak, devops, fs |
Мои проекти на Desktop |
Всички пътища са към моя Windows потребител (/mnt/c/Users/fedia/…). Когато си го приспособявате, сменете fedia с вашето име. Ако не искате да го повтаряте на всеки ред, задайте го веднъж и го ползвайте във всички:
WINHOME=/mnt/c/Users/ВАШЕТО_ИМЕ
alias desktop='cd $WINHOME/Desktop'
alias nex='cd $WINHOME/Nextcloud'
Единичните кавички са важни: така $WINHOME се разгъва при изпълнение, а не при зареждане.
10. SSH / Security
| Alias | Какво прави |
|---|---|
sship |
ssh без проверка на host key, без запис в known_hosts и без предупреждения |
Ползване: sship user@192.168.1.50.
⚠️ Използвайте
sshipсамо за тестови машини, които често преинсталирам и които получават нов host key при всеки път. Проверката на host key е защитата срещу подмяна на сървъра (man-in-the-middle атака), а този alias я изключва. За постоянни сървъри използвайте обикновенssh.
11. Notifications
| Alias | Какво прави |
|---|---|
alert |
Показва системно известие, когато дълга команда приключи |
Ползва се така: sleep 30; alert. Известието е със заглавието на командата и различна иконка при успех и грешка. Това е стандартният alert от Ubuntu. Изисква notify-send (пакет libnotify-bin) и десктоп среда, така че в WSL често не работи без допълнителна настройка.
Файл 2: ~/.bashrc
След като alias-ите излязоха, .bashrc стана по-кратък и съдържа само настройки, инструменти и функции. Тук вече няма нито един alias – всички са във ~/.fedya_aliases.
# ~/.bashrc — Cleaned & Organized Version
# 1. Интерактивна проверка
case $- in
*i*) ;;
*) return;;
esac
# 2. История на командите (History setup)
HISTCONTROL=ignoreboth
HISTFILESIZE=1000000
HISTSIZE=1000000
export HISTTIMEFORMAT="%d-%m-%Y %T "
shopt -s histappend
export PROMPT_COMMAND='history -a'
# 3. Настройки на терминала
shopt -s checkwinsize
[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"
if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then
debian_chroot=$(cat /etc/debian_chroot)
fi
# 4. Prompt (Оцветен промпт)
case "$TERM" in
xterm-color|*-256color) color_prompt=yes;;
esac
if [ "$color_prompt" = yes ]; then
PS1="\[\033[38;5;209m\]\u\[\033[38;5;154m\]@\[\033[38;5;46m\]\h \[\033[38;5;226m\]\w \[\033[0m\]\[\033[38;5;15m\]$ \[\033[0m\]"
else
PS1="\[$(tput setaf 209)\]\u\[$(tput setaf 154)\]@\[$(tput setaf 46)\]\h \[$(tput setaf 226)\]\w \[$(tput sgr0)\]\[$(tput setaf 15)\]$ \[$(tput sgr0)\]"
fi
unset color_prompt force_color_prompt
case "$TERM" in
xterm*|rxvt*)
PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1"
;;
*)
;;
esac
# 5. Цветове за dircolors
if [ -x /usr/bin/dircolors ]; then
test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
fi
# 6. Външни инструменти (Keychain, Starship, NVM)
eval $(keychain --quiet --eval \
~/.ssh/fedia007_rsa \
~/.ssh/id_ed25519 \
~/.ssh/tablet.id_rsa
)
eval "$(starship init bash)"
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"
# 7. Автодопълване (Bash completion)
if ! shopt -oq posix; then
if [ -f /usr/share/bash-completion/bash_completion ]; then
. /usr/share/bash-completion/bash_completion
elif [ -f /etc/bash_completion ]; then
. /etc/bash_completion
fi
fi
# ==========================================
# ПОТРЕБИТЕЛСКИ ФУНКЦИИ (FUNCTIONS)
# ==========================================
# Proxmox Backup
backup_ct() {
local ct_id="$1"
local server="prox"
local remote_path="/backup512/dump"
local local_path="/mnt/d/backup_proxmox"
if [ -z "$ct_id" ]; then
echo "❗ Употреба: backup_ct <CT_ID>"
return 1
fi
echo "🔍 Търсене на най-нов архив за контейнер $ct_id..."
local latest=$(ssh $server "ls -t $remote_path/vzdump-lxc-${ct_id}-*.tar.zst 2>/dev/null | head -1")
if [ -z "$latest" ]; then
echo "❌ Архив не е намерен за контейнер $ct_id"
return 1
fi
local filename=$(basename "$latest")
echo "📦 Копиране на $filename"
if rsync -avz --progress $server:"$latest" "$local_path/"; then
echo "✅ Успешно копиране завършено!"
else
echo "❌ Грешка при копирането"
return 1
fi
}
# Система за управление на Linux команди (fzf)
cmd() {
local selected=$(cat ~/.commands.txt | grep -v "^#" | grep -v "^$" | \
fzf --height=80% \
--layout=reverse \
--border=rounded \
--margin=1 \
--padding=1 \
--info=inline \
--prompt="🔍 Търси команда: " \
--pointer="▶" \
--marker="✓" \
--color="fg:#d0d0d0,bg:#1e1e1e,hl:#5f87af" \
--color="fg+:#ffffff,bg+:#3a3a3a,hl+:#5fd7ff" \
--color="info:#af87ff,prompt:#5fd7ff,pointer:#ff5f5f" \
--color="marker:#87ff00,spinner:#ff87d7,header:#87afaf" \
--preview='echo -e "\033[1;36mОписание:\033[0m" && echo {} | cut -d"|" -f1 | sed "s/^[ \t]*//" && echo -e "\n\033[1;33mТагове:\033[0m" && echo {} | cut -d"|" -f3 | sed "s/^[ \t]*//" && echo -e "\n\033[1;32mКоманда:\033[0m" && echo {} | sed "s/.*|| //"' \
--preview-window=right:40%:wrap)
if [ -n "$selected" ]; then
local command=$(echo "$selected" | sed 's/.*|| //')
if grep -qi microsoft /proc/version; then
echo "$command" | clip.exe
else
echo "$command" | xclip -sel clip
fi
echo -e "\033[1;32m✓ Копирано:\033[0m $command"
fi
}
# FZF история (Ctrl+H)
find_history_fzf() {
local selected_command
selected_command=$(history | fzf --tac --height 40% \
--layout=reverse --border --ansi \
--header="📜 История (Ctrl+H) | Най-новите са отгоре" \
--tiebreak=index \
--color="header:italic,fg:110,border:93" \
--preview='echo {}' --preview-window=bottom:3:wrap)
if [ -n "$selected_command" ]; then
local clean_cmd=$(echo "$selected_command" | sed -E 's/^[ ]*[0-9]+[ ]+[0-9]{2}-[0-9]{2}-[0-9]{4} [0-9]{2}:[0-9]{2}:[0-9]{2}[ ]+//')
READLINE_LINE="$clean_cmd"
READLINE_POINT=${#READLINE_LINE}
fi
}
bind -x '"\C-h": find_history_fzf'
# Бекъп на директория
bekap() {
local ext="${1:-}"
local dest="_backup_$(date +%Y%m%d_%H%M%S)"
local pattern
if [ -z "$ext" ] || [ "$ext" = "*" ]; then
pattern="*"
else
pattern="*.${ext}"
fi
mkdir -p "$dest"
find . \
-type f \
-name "$pattern" \
-not -path "./_backup_*/*" \
-not -path "./.git/*" \
-exec cp --parents {} "$dest/" \;
local count
count=$(find "$dest" -type f | wc -l)
echo "Бекъп готов: $dest ($count файла, pattern: $pattern)"
}
# Замяна на файл от клипборда
zameni() {
if [ -z "$1" ]; then
echo "Грешка: Трябва да зададеш име на файла!" >&2
echo "Употреба: zameni <име_на_файла>" >&2
return 1
fi
if ! command -v xclip >/dev/null 2>&1; then
echo "Грешка: Пакетът 'xclip' не е инсталиран (sudo apt install xclip)." >&2
return 1
fi
local content
content=$(xclip -selection clipboard -o 2>/dev/null)
if [ -z "$content" ]; then
echo "Грешка: Клипбордът е празен! Файлът '$1' НЕ е променен." >&2
return 1
fi
printf '%s\n' "$content" > "$1" && echo "Файлът '$1' е успешно презаписан."
}
# Git quick push
gp() {
if [ -n "$(git status --porcelain)" ]; then
git add -A
local files_count
files_count=$(git diff --cached --name-only | wc -l | tr -d ' ')
if [ -n "$1" ]; then
git commit -m "Perf: $1 ($files_count file(s))"
else
local timestamp
timestamp=$(date +"%Y-%m-%d %H:%M")
git commit -m "Auto-commit: $files_count file(s) at $timestamp"
fi
git push origin main
else
echo "Няма промени за комит."
fi
}
# ==========================================
# ЗАРЕЖДАНЕ НА ЛИЧНИТЕ ALIASES
# ==========================================
if [ -f ~/.fedya_aliases ]; then
. ~/.fedya_aliases
fi
Настройки (секции 1–5)
1. Интерактивна проверка. Ако Bash не е интерактивен (например при scp или скрипт), файлът спира тук. Така неинтерактивните сесии не зареждат промпт, цветове и не печатат нищо излишно.
2. История на командите.
| Настройка | Ефект |
|---|---|
HISTCONTROL=ignoreboth |
Не записва команди, започващи с интервал, и дублирани подред команди |
HISTSIZE / HISTFILESIZE = 1000000 |
Пази до милион команди в паметта и във файла |
HISTTIMEFORMAT="%d-%m-%Y %T " |
history показва дата и час на всяка команда |
shopt -s histappend |
Файлът с историята се допълва, а не се презаписва при излизане |
PROMPT_COMMAND='history -a' |
Записва всяка команда във файла веднага след изпълнението ѝ |
Последната настройка означава, че историята не се губи, ако терминалът се затвори неочаквано, и че нови терминали виждат командите от вече отворените. Отворените терминали не четат файла автоматично; за да получат чуждите команди, трябва да изпълните history -n.
3. Настройки на терминала. checkwinsize обновява размера на прозореца след всяка команда, а lesspipe позволява на less да показва и файлове, които не са чист текст (архиви, PDF). Блокът с debian_chroot е от стандартния Ubuntu .bashrc и показва в промпта, ако работите в chroot.
4. Промпт. PS1 е нарисуван с 256-цветови кодове: потребителят в оранжево, @ в светлозелено, хостът в зелено, пътят в жълто. Вторият блок case слага user@host: папка в заглавието на прозореца. Тъй като в секция 6 зареждам Starship, който поема промпта, този блок реално остава като резервен вариант, ако Starship не е наличен.
5. Цветове за ls. Зареждат се от ~/.dircolors, ако файлът съществува, иначе се ползват стандартните.
Външни инструменти (секция 6)
- keychain пуска
ssh-agent(ако още не работи) и зарежда трите ми SSH ключа, като споделя агента между всички терминали. Паролата на ключа се пита един път, при първия терминал. В WSL агентът умира приwsl --shutdown, включително когато го извиква функциятаwslbackupот предишната ми статия, така че паролата ще трябва да се въведе отново. - Starship е промптът, който показва git клон, версии на инструменти и статус на последната команда.
- NVM управлява версиите на Node.js. Обратната наклонена черта в
\.е част от стандартния сниппет на NVM и предпазва от евентуален alias на.. - Bash completion (секция 7) е автодопълването с
Tab.
Ако копирате моя
.bashrc, а нямате тези инструменти, при всяко отваряне на терминал ще виждате грешки. Инсталирайте ги или предпазете реда с проверка, например за Starship:command -v starship >/dev/null && eval "$(starship init bash)"Същият подход върши работа и за
keychain. Ако някой от ключовете липсва на диска, keychain ще се оплаче при всеки терминал, затова оставете само ключовете, които наистина ползвате.
Функции и как се работят с тях
backup_ct – теглене на Proxmox бекъп
backup_ct 114 # най-новият бекъп на контейнер 114
backups_wp # същото, чрез alias-а за контейнер 114
Функцията се свързва по SSH към хоста prox, търси в /backup512/dump най-новия файл vzdump-lxc-<ID>-*.tar.zst (подрежда ги по време на промяна с ls -t) и го копира с rsync в /mnt/d/backup_proxmox. Примерен изход:
🔍 Търсене на най-нов архив за контейнер 114...
📦 Копиране на vzdump-lxc-114-2026_09_20-03_00_02.tar.zst
...
✅ Успешно копиране завършено!
Изисква Host prox в ~/.ssh/config (стойностите са примерни):
Host prox
HostName 192.168.1.10
User root
IdentityFile ~/.ssh/id_ed25519
и rsync на двете машини. Без ID функцията показва „Употреба“ и спира.
cmd – търсене в базата с команди
cmd
Отваря fzf върху ~/.commands.txt (форматът е описан в секция 08 на alias-ите). Пишете част от описанието, тага или командата и виждате в панел вдясно описанието, таговете и самата команда. С Enter командата се копира в клипборда: в WSL през clip.exe (тогава я поставяте с Ctrl+V във Windows Terminal), а на обикновен Linux през xclip.
Не пишете
||вътре в самата команда, защотоcmdвзема като команда всичко след последното||и ще я отреже. Ако ви трябва „или“, ползвайте;или функция.
find_history_fzf – търсене в историята с Ctrl+H
Натискате Ctrl+H, пишете част от команда и с Enter избраната команда се появява на командния ред. Не се изпълнява веднага, така че можете да я поправите. Най-новите команди са най-отгоре.
Как работи: bind -x свързва клавишната комбинация с функцията, а функцията записва избраното в READLINE_LINE. Регулярният израз в sed маха номера и датата от началото на реда, като разчита на формата на HISTTIMEFORMAT. Ако смените HISTTIMEFORMAT, поправете и sed-а.
В някои терминали клавишът Backspace изпраща същия код като
Ctrl+H, и тогава триенето спира да работи. При мен Windows Terminal ги различава. Ако при вас е проблем, изберете друга свободна комбинация (bind -Pпоказва заетите).
bekap – бърз бекъп на файлове в текущата папка
bekap # копира всички файлове
bekap md # само *.md
bekap sh # само *.sh
Създава папка _backup_ГГГГММДД_ЧЧММСС в текущата директория и копира файловете в нея със запазена структура на подпапките (cp --parents). Пропуска .git и предишните бекъпи (_backup_*). Разширението се подава без точка. Накрая показва колко файла са копирани.
В Node проекти
bekapкопира иnode_modules, което може да е огромно. Добавете още един ред къмfind, до другите-not -path:-not -path "./node_modules/*" \
zameni – замяна на файл със съдържанието на клипборда
zameni script.sh
Презаписва script.sh с това, което е в клипборда. Ползвам я, когато копирам нова версия на файл от чата или от браузъра. Защитите са две: не работи без име на файл и не пипа файла, ако клипбордът е празен. Презаписва без питане и без копие, затова на важни файлове първо пуснете bekap. Изисква xclip (sudo apt install xclip).
gp – git commit и push с една команда
gp # автоматично съобщение
gp "поправка на менюто"
Ако има промени, gp изпълнява git add -A, прави commit и праща към origin main. Съобщението е:
- без аргумент:
Auto-commit: N file(s) at 2026-09-21 14:30 - с аргумент:
Perf: поправка на менюто (N file(s))
Ако няма промени, пише „Няма промени за комит“. Две неща, които трябва да знаете: git add -A добавя всичко, включително нови файлове, затова проверявайте .gitignore; и gp винаги праща към main, независимо на кой клон сте.
Как да намеря забравен alias или функция
С времето се събират десетки alias-и и функции и е нормално да забравите как се казва някой от тях. Затова имам няколко начина за търсене, според това какво си спомням:
| Знам… | Ползвам |
|---|---|
| част от името или от командата | aliases дума |
| само какво прави | fa или grep -i -C1 "дума" ~/.bashrc ~/.fedya_aliases |
| точното име, но не помня какво прави | type име или declare -f име |
aliases дума – бързо търсене по име или команда
aliases docker # alias-и с "docker" в името или в командата
aliases StrictHost # намира sship, защото търси и в самата команда
aliases zameni # zameni е функция, затова излиза с "(функция)"
Ако няма съвпадение, пише „Няма съвпадения за: …“. Функциите се търсят само по име, не по съдържание. Това е важно, защото zameni е функция, а не alias, и обикновеното alias | grep zameni няма да я намери.
fa – интерактивно търсене с описание
fa
fa отваря fzf със списък на всички alias-и [A] и функции [F]. Пишете каквото да е и списъкът се стеснява на живо. Всеки ред има описание, затова се търси и по смисъл: „клипборд“ намира zameni, „бекъп“ намира bekap. Примерен изход:
[A] dlf docker logs -f # Следене на container logs
[A] sship ssh -o StrictHostKeyChecking=no ... # SSH без проверка на host key
[F] zameni # Замяна на файл от клипборда
[F] bekap # Бекъп на директория
[F] gp # Git quick push
Enter затваря списъка и показва цялата дефиниция на избрания ред: за функция – кода ѝ, за alias – в какво се разгъва. Esc затваря без нищо да прави.
Как работи (функцията е във ~/.fedya_aliases, секция 01):
- Описанията се четат с
awkот двата файла. Описание е първият коментар над дефиницията, затова е добре да пишете кратки, ясни коментари. - Списъкът идва от живата сесия:
compgen -A aliasза alias-ите иcompgen -A functionза функциите. Така се виждат и alias-и, дефинирани в друг файл. - Филтърът
grep -Ev '^(_|nvm|starship)'скрива вътрешните функции на bash-completion, NVM и Starship. Без него те потопяват вашите. - След
Entertype имепоказва дефиницията.head -1гарантира, че при няколко избрани реда се ползва първият.
Кратки бележки:
-
Описанието идва от коментара непосредствено над дефиницията, например:
# Замяна на файл от клипборда <- това става описанието на zameni zameni() {Ако искате повече подробности, допишете коментара.
-
Всички аргументи на
faсе подават наfzf, напримерfa --height 60%. -
Ако в списъка се появят други излишни функции, добавете имената им във филтъра. Например
quote,dequoteиquote_readlineот bash-completion се скриват с(_|nvm|starship|quote|dequote). -
Пътищата
~/.bashrcи~/.fedya_aliasesса в края наawkреда. Ако файловете ви са другаде, сменете ги. -
fzfтърси приблизително, така че къса дума може да покаже и неочаквани редове. Изисква инсталиранfzf.
Търсене по смисъл без fzf
grep -i -C1 "бекъп" ~/.fedya_aliases ~/.bashrc
-C1 показва по един ред отгоре и отдолу, така че виждате коментара до самата дефиниция. Работи навсякъде, дори без fzf.
Как да приложите всичко при себе си
-
Направете копие на сегашния
.bashrc, за да имате път назад:cp ~/.bashrc ~/.bashrc.bak -
Създайте
~/.fedya_aliases, поставете кода от тази статия и сменете личните пътища (потребител, проекти, сървъри):nano ~/.fedya_aliases -
Добавете блока за зареждане в края на
.bashrc(командата е в началото на статията). -
Инсталирайте зависимостите, които ползвате:
sudo apt install fzf keychain xclip rsync python3-pygmentsStarship и NVM се инсталират по инструкциите на самите проекти.
-
Проверете синтаксиса, преди да отворите нов терминал:
bash -n ~/.bashrc && bash -n ~/.fedya_aliases && echo "OK" -
Отворете нов терминал и пуснете
aliases, за да видите, че всичко е заредено.
Ако нещо се счупи, bash --norc стартира чист Bash без вашите настройки, откъдето можете да поправите файла или да върнете копието:
cp ~/.bashrc.bak ~/.bashrc
Как да пазя двата файла
Двата файла са малки и лични, затова ги пазя на едно място и правя символични връзки към тях. Например в Git хранилище dotfiles (частно, тъй като файловете съдържат имена на сървъри и пътища):
ln -s ~/dotfiles/.fedya_aliases ~/.fedya_aliases
ln -s ~/dotfiles/.bashrc ~/.bashrc
Така при нова машина или нова WSL дистрибуция е достатъчно да клонирам хранилището и да пусна двете команди.
Alias или функция?
Когато добавяте нова команда, изборът е прост:
| Ползвайте | Когато |
|---|---|
alias (във ~/.fedya_aliases) |
Командата е просто по-кратко име за друга команда, евентуално с опции. Аргументите се добавят накрая, например dlf име |
функция (в ~/.bashrc) |
Ви трябват аргументи някъде по средата, проверки, условия или няколко стъпки. Примери: backup_ct, bekap, gp |
Полезни команди при работа с alias-и: alias име (показва как е дефиниран), type име (показва дали е alias, функция или програма), unalias име (премахва го за сесията). Ако сте забравили как се казва, ползвайте fa.
Заключение
Разделянето на един файл на два ми даде най-вече спокойствие: настройките и функциите са на едно място, alias-ите на друго, и всяко се променя, без да се плаша, че ще счупя другото. Единственото, което свързва двата файла, е блокът от четири реда в края на .bashrc.
Не е нужно да вземате всичко. Прегледайте секциите, вземете само alias-ите, които ще ползвате, и си добавете свои. Най-полезните за мен се оказаха fa за търсене на забравен alias или функция, cmd с базата с команди и Ctrl+H за търсене в историята.