Files
dotfiles/dot_config/zsh/config/functions.zsh
T

335 lines
11 KiB
Bash

# ════════════════════════════════════════════════════════════
# Custom Functions
# ════════════════════════════════════════════════════════════
# ═══ Навигация ═════════════════════════════════════════════
# mkcd - создать директорию и перейти в неё
mkcd() {
mkdir -p "$1" && cd "$1"
}
# up - подняться на N уровней вверх
up() {
local d=""
local limit="${1:-1}"
for ((i=1; i<=limit; i++)); do
d="../$d"
done
if [[ -z "$d" ]]; then
d=..
fi
cd "$d" || return
}
# ═══ Поиск ═════════════════════════════════════════════════
# ff - быстрый поиск файлов
ff() {
if command -v fd &>/dev/null; then
fd "$@"
else
find . -iname "*$1*"
fi
}
# fh - поиск в истории команд с fzf
fh() {
if command -v fzf &>/dev/null; then
print -z $(history -n 1 | fzf --tac --no-sort)
else
history | grep "$1"
fi
}
# ═══ Файлы и директории ════════════════════════════════════
# extract - универсальная распаковка (если плагин не загружен)
if ! command -v extract &>/dev/null; then
extract() {
if [[ -f $1 ]]; then
case $1 in
*.tar.bz2) tar xjf "$1" ;;
*.tar.gz) tar xzf "$1" ;;
*.tar.xz) tar xJf "$1" ;;
*.bz2) bunzip2 "$1" ;;
*.rar) unrar x "$1" ;;
*.gz) gunzip "$1" ;;
*.tar) tar xf "$1" ;;
*.tbz2) tar xjf "$1" ;;
*.tgz) tar xzf "$1" ;;
*.zip) unzip "$1" ;;
*.Z) uncompress "$1" ;;
*.7z) 7z x "$1" ;;
*) echo "'$1' cannot be extracted via extract()" ;;
esac
else
echo "'$1' is not a valid file"
fi
}
fi
# backup - создать резервную копию файла
backup() {
if [[ -f $1 ]]; then
cp "$1"{,.backup-$(date +%Y%m%d-%H%M%S)}
echo "Backup created: $1.backup-$(date +%Y%m%d-%H%M%S)"
else
echo "File not found: $1"
fi
}
# ═══ Размер файлов ═════════════════════════════════════════
# dirsize - показать размер директории
dirsize() {
du -sh "${1:-.}" 2>/dev/null || echo "Directory not found"
}
# largest - показать N самых больших файлов в директории
largest() {
local num=${1:-10}
du -ah "${2:-.}" | sort -rh | head -n "$num"
}
# ═══ Процессы ══════════════════════════════════════════════
# psgrep - поиск процессов
psgrep() {
ps aux | grep -v grep | grep -i -e VSZ -e "$1"
}
# kill процесс по имени
killp() {
local pid
pid=$(ps aux | grep -v grep | grep "$1" | awk '{print $2}')
if [[ -n $pid ]]; then
echo "Killing process: $1 (PID: $pid)"
kill -9 "$pid"
else
echo "Process not found: $1"
fi
}
# ═══ Сеть ══════════════════════════════════════════════════
# myip - показать все IP адреса
myip() {
echo "External IP: $(curl -s ifconfig.me)"
echo "Local IPs:"
ip -4 addr show | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | grep -v 127.0.0.1
}
# ports - показать открытые порты
openports() {
sudo netstat -tulanp | grep LISTEN
}
# ═══ Git ═══════════════════════════════════════════════════
# gitignore - скачать .gitignore для языка
gitignore() {
if [[ -z $1 ]]; then
echo "Usage: gitignore <language>"
return 1
fi
curl -sL "https://www.toptal.com/developers/gitignore/api/$1" -o .gitignore
echo ".gitignore created for: $1"
}
# gclone - клонировать репозиторий и перейти в него
gclone() {
if [[ -z $1 ]]; then
echo "Usage: gclone <repository>"
return 1
fi
local repo_name=$(basename "$1" .git)
git clone "$1" && cd "$repo_name" || return
}
# ═══ Разработка ════════════════════════════════════════════
# serve - быстрый HTTP сервер
serve() {
local port="${1:-8000}"
if command -v python3 &>/dev/null; then
echo "Starting server on http://localhost:$port"
python3 -m http.server "$port"
else
echo "Python3 not found"
fi
}
# json - форматировать JSON
json() {
if [[ -f $1 ]]; then
python3 -m json.tool "$1"
else
echo "$1" | python3 -m json.tool
fi
}
# ═══ Утилиты ═══════════════════════════════════════════════
# weather - погода для города
weather() {
local city="${1:-Moscow}"
curl -s "wttr.in/$city?format=3"
}
# Функция для монтирования облаков
mount-clouds() {
mkdir -p ~/YaDisk ~/GDrive
echo "Монтирую диски..."
# Яндекс.Диск
rclone mount yadisk: ~/YaDisk \
--vfs-cache-mode writes \
--vfs-cache-max-size 10G \
--vfs-cache-max-age 2h \
--allow-non-empty \
--daemon
# Google Drive
rclone mount gdrive: ~/GDrive \
--vfs-cache-mode writes \
--vfs-cache-max-size 10G \
--vfs-cache-max-age 2h \
--allow-non-empty \
--daemon
echo "Готово! Проверяю монтирование:"
ls ~/YaDisk >/dev/null 2>&1 && echo "✅ YaDisk смонтирован" || echo "⚠️ Ошибка монтирования YaDisk"
ls ~/GDrive >/dev/null 2>&1 && echo "✅ GDrive смонтирован" || echo "⚠️ Ошибка монтирования GDrive"
}
# Функция для размонтирования
unmount-clouds() {
echo "Отключаю диски..."
fusermount -uz ~/YaDisk 2>/dev/null && echo "✅ YaDisk отключен" || echo "⚠️ YaDisk не был примонтирован"
fusermount -uz ~/GDrive 2>/dev/null && echo "✅ GDrive отключен" || echo "⚠️ GDrive не был примонтирован"
}
SSH_PROXY_PID_FILE="/tmp/ssh_proxy.pid"
# Адрес Privoxy, который слушает HTTP и перенаправляет в SOCKS5
# 1. Запуск
sshp-start() {
if [ -f "$SSH_PROXY_PID_FILE" ] && kill -0 $(cat "$SSH_PROXY_PID_FILE") 2>/dev/null; then
echo "Ошибка: Прокси уже запущен (PID: $(cat $SSH_PROXY_PID_FILE))"
return 1
fi
# Запуск SSH в фоновом режиме
ssh -fN -D 127.0.0.1:1080 fl-vps
# Сохранение PID последнего запущенного процесса
pgrep -f "ssh -fN -D 127.0.0.1:1080 fl-vps" > "$SSH_PROXY_PID_FILE"
echo "SSH прокси (SOCKS5) запущен на 127.0.0.1:1080."
}
# 2. Остановка
sshp-stop() {
if [ -f "$SSH_PROXY_PID_FILE" ]; then
PID=$(cat "$SSH_PROXY_PID_FILE")
if kill "$PID" 2>/dev/null; then
rm -f "$SSH_PROXY_PID_FILE"
echo "SSH прокси (PID $PID) остановлен."
else
echo "Процесс $PID не найден. Очистка PID-файла..."
rm -f "$SSH_PROXY_PID_FILE"
fi
else
echo "Ошибка: Прокси не запущен."
fi
}
# 3. Статус
sshp-status() {
if [ -f "$SSH_PROXY_PID_FILE" ] && kill -0 $(cat "$SSH_PROXY_PID_FILE") 2>/dev/null; then
PID=$(cat "$SSH_PROXY_PID_FILE")
echo "Статус: РАБОТАЕТ (PID: $PID)"
# Проверка прослушивания порта
lsof -i -nP | grep "$PID" | grep LISTEN
else
echo "Статус: ОСТАНОВЛЕН"
fi
}
sshp-restart() {
sshp-stop
sleep 1
sshp-start
}
# _backup_reminder - проверить давность последнего бэкапа (вызывается из .zshrc)
_backup_reminder() {
local state_file="${XDG_STATE_HOME:-$HOME/.local/state}/backup-last-run"
local threshold=$(( 2 * 24 * 3600 )) # 2 дня в секундах
local now
now=$(date +%s)
if [[ ! -f "$state_file" ]]; then
print -P "%F{yellow}⚠ Бэкап не запускался. Запусти: backup-menu%f"
return
fi
local last
last=$(cat "$state_file")
local diff=$(( now - last ))
if (( diff > threshold )); then
local days=$(( diff / 86400 ))
print -P "%F{yellow}⚠ Последний бэкап: ${days} дн. назад. Запусти: backup-menu%f"
fi
}
# proj - перейти в проект через fzf
proj() {
local base="${PROJECTS_DIR:-$HOME/Documents/Projects}"
if [[ ! -d "$base" ]]; then
echo "Projects dir not found: $base"
return 1
fi
local target
if command -v fzf &>/dev/null; then
target=$(find "$base" -maxdepth 2 -mindepth 1 -type d \
\( -name .git -o -name node_modules -o -name .venv \) -prune \
-o -type d -print \
| sed "s|$base/||" \
| fzf --prompt "proj > " --height=40% --reverse) || return 0
elif [[ -n "$1" ]]; then
target="$1"
else
ls "$base"
return 0
fi
cd "$base/$target"
}
activate() {
local venv_dir=""
if [[ -d ".venv" ]]; then
venv_dir=".venv"
elif [[ -d "venv" ]]; then
venv_dir="venv"
else
for venv_dir in **/.venv **/venv; do
[[ -d "$venv_dir" ]] && break
done
fi
if [[ -n "$venv_dir" && -f "$venv_dir/bin/activate" ]]; then
source "$venv_dir/bin/activate"
else
echo "venv/.venv not found"
return 1
fi
}