13 небольших Bash-скриптов, которые ежедневно экономят время
Это перевод оригинальной статьи 13 Tiny Bash Scripts That Save Me Time Every Day.
Подписывайтесь на телеграм-канал usr_bin, где я публикую много полезного по Linux, в том числе ссылки на статьи в этом блоге.
Простые shell-скрипты, которые можно использовать каждый день и которые повысят производительность.
Вам не нужен Bash-скрипт на 500 строк.
Когда люди думают о shell-скриптах, они часто представляют себе огромные скрипты с множеством функций, переменных и сложной логикой, которые выполняют большие задачи. В результате многие новички считают, что shell-скрипты слишком сложны для них, и продолжают вводить команды по одной.
Shell-скрипты не обязаны быть сложными. Простой скрипт на 10 строк, который избавляет нас от необходимости каждый день вводить одни и те же команды, может быть невероятно полезным. Он экономит время, уменьшает количество ошибок, сокращает объем повторяющейся работы и делает наши повседневные задачи проще и эффективнее.
В этой статье мы рассмотрим практические Bash-скрипты, которые короткие, простые для понимания и решают распространенные повседневные задачи.
#1. Создавайте резервную копию перед редактированием файлов
Одно из золотых правил системного администрирования — всегда создавать резервные копии перед редактированием важного файла. Независимо от того, редактируете ли вы /etc/nginx/nginx.conf, /etc/ssh/sshd_config или файл .env, наличие резервной копии позволяет быстро восстановить оригинал, если что-то пойдет не так.
Конечно, cp file.conf file.conf.bak работает идеально. Но вводить одну и ту же команду каждый раз при редактировании файла становится утомительно. Небольшой Bash-скрипт может сделать то же самое с помощью более короткой и простой команды.
#!/usr/bin/env bash
# bak - create a timestamped backup of a file
# Usage: bak <file> [file ...]
set -euo pipefail
if [[ $# -eq 0 ]]; then
echo "Usage: bak <file> [file ...]" >&2
exit 1
fi
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
for file in "$@"; do
if [[ ! -e "$file" ]]; then
echo "bak: '$file' not found" >&2
continue
fi
backup="${file}.${TIMESTAMP}.bak"
cp -a -- "$file" "$backup"
echo "Created backup: $backup"
done#Usage: bak /etc/nginx/nginx.conf # Created backup: /etc/nginx/nginx.conf.20260618-143015.bak bak ~/.bashrc ~/.vimrc # Multiple input # Created backup: /home/user/.bashrc.20260618-143027.bak # Created backup: /home/user/.vimrc.20260618-143027.bak
Вместо того чтобы дважды вводить длинные пути в команде cp file.conf file.conf.bak, этот скрипт автоматизирует процесс и добавляет точную временную метку, чтобы избежать перезаписи предыдущих резервных копий.
Примечание: Чтобы использоватьbakкак команду, убедитесь, что скрипт находится в каталоге, который входит вPATH(например,~/bin), сделайте его исполняемым с помощьюchmod +xи перезагрузите конфигурацию shell (source ~/.bashrc).
$PATH: Переменная, управляющая всей вашей цепочкой инструментов
Перестаньте быть обычным пользователем! Освойте $PATH и станьте продвинутым пользователем.
#2. Создавайте каталог и сразу переходите в него
Создание новой директории и последующий переход в неё — это то, что многие из нас делают несколько раз в день, особенно при начале нового проекта или организации файлов.
Мы всегда можем выполнить mkdir -p complex/path/to/project, затем cd complex/path/to/project, или объединить их в одну команду: mkdir -p complex/path/to/project && cd complex/path/to/project. Это работает идеально, но каждый раз вводить одну и ту же длинную команду — больше усилий, чем должно требоваться для такой распространенной задачи.
# Add to ~/.bashrc - not a standalone script, needs to be a function
mkcd() {
if [ -z "$1" ]; then
echo "Usage: mkcd <directory_path>"
return 1
fi
mkdir -p "$1" && cd "$1"
}# Usage: mkcd my-project mkcd projects/rust/axum-demo # Create nested directories if they don't already exist mkcd "My New Project" # Use quotes for directory names that contain spaces
Благодаря mkcd создание каталога и переход в него становится операцией в один шаг, что экономит несколько нажатий клавиш каждый раз, когда мы начинаем новый проект.
Примечание:
Отдельный Bash-скрипт не может изменить текущий рабочий каталог терминала, который его запускает. Любая команда cd внутри скрипта влияет только на сам скрипт, и после его завершения терминал остается в исходном каталоге. Именно поэтому здесь используется функция shell.#3. Распаковывайте любой архив
Сжатые файлы бывают самых разных форматов, таких как .zip, .tar.gz, .tgz, .tar.bz2 и .tar.xz. Проблема в том, что для каждого формата существует своя команда распаковки, которую бывает трудно запомнить.
#!/usr/bin/env bash
# extract — universal archive extractor
# Usage: extract <file> [file ...]
set -euo pipefail
if [[ $# -eq 0 ]]; then
echo "Usage: extract <archive> [archive ...]" >&2
exit 1
fi
for file in "$@"; do
if [[ ! -f "$file" ]]; then
echo "extract: '$file' not found" >&2
continue
fi
echo "Extracting: $file"
case "$file" in
*.tar.bz2|*.tbz2) tar xjf "$file" ;;
*.tar.gz|*.tgz) tar xzf "$file" ;;
*.tar.xz|*.txz) tar xJf "$file" ;;
*.tar.zst) tar --zstd -xf "$file" ;;
*.tar) tar xf "$file" ;;
*.bz2) bunzip2 "$file" ;;
*.gz) gunzip "$file" ;;
*.xz) unxz "$file" ;;
*.zip) unzip "$file" ;;
*.7z) 7z x "$file" ;;
*.rar) unrar x "$file" ;;
*.Z) uncompress "$file" ;;
*.deb)
mkdir -p "${file%.deb}"
dpkg-deb -xv "$file" "${file%.deb}"
;;
*.rpm)
mkdir -p "${file%.rpm}"
cd "${file%.rpm}" && rpm2cpio "../$file" | cpio -idmv
cd ..
;;
*)
echo "extract: unknown format — '$file'" >&2
;;
esac
done# Usage: extract archive.tar.gz extract file1.zip file2.tar.bz2 file3.7z # multiple at once
Вместо того чтобы запоминать отдельную команду для каждого формата архива, нам достаточно запомнить только одну: extract <filename>. Скрипт автоматически определяет тип файла и запускает правильную команду распаковки. Он поддерживает практически все форматы архивов, с которыми мы сталкиваемся в повседневной работе.
Примечание:
Для некоторых форматов архивов требуются дополнительные утилиты. Например, для распаковки файлов.rarнеобходимunrar, а для распаковки.7z—p7zip(илиp7zip-fullв Debian/Ubuntu).
#4. Сжимайте файлы и каталоги удобным способом
Создание архивов так же распространено, как и их распаковка. Создаем ли мы резервную копию проекта, делимся файлами или архивируем логи — нам часто приходится запоминать разные команды в зависимости от того, что именно мы сжимаем и какой формат архива хотим получить.
#!/usr/bin/env bash
# compress — compress files or directories
# Usage: compress <target> [format]
# Formats: gz (default), bz2, xz, zip, zst
set -euo pipefail
TARGET="${1:-}"
FORMAT="${2:-gz}"
if [[ -z "$TARGET" ]]; then
echo "Usage: compress <file-or-dir> [gz|bz2|xz|zip|zst]" >&2
exit 1
fi
if [[ ! -e "$TARGET" ]]; then
echo "compress: '$TARGET' not found" >&2
exit 1
fi
# Strip trailing slash
TARGET="${TARGET%/}"
NAME=$(basename "$TARGET")
STAMP=$(date +"%Y%m%d_%H%M%S")
case "$FORMAT" in
gz)
OUTPUT="${NAME}_${STAMP}.tar.gz"
tar czf "$OUTPUT" "$TARGET"
;;
bz2)
OUTPUT="${NAME}_${STAMP}.tar.bz2"
tar cjf "$OUTPUT" "$TARGET"
;;
xz)
OUTPUT="${NAME}_${STAMP}.tar.xz"
tar cJf "$OUTPUT" "$TARGET"
;;
zst)
OUTPUT="${NAME}_${STAMP}.tar.zst"
tar --zstd -cf "$OUTPUT" "$TARGET"
;;
zip)
OUTPUT="${NAME}_${STAMP}.zip"
zip -r "$OUTPUT" "$TARGET"
;;
*)
echo "compress: unknown format '$FORMAT'. Use: gz bz2 xz zst zip" >&2
exit 1
;;
esac
SIZE=$(du -sh "$OUTPUT" | cut -f1)
echo " Created: $OUTPUT ($SIZE)"compress ./my-project # → my-project_20240617_143022.tar.gz compress ./logs bz2 # → logs_20240617_143022.tar.bz2 compress config.yml zip # → config.yml_20240617_143022.zip
Этот скрипт позволяет сжимать файлы или каталоги в формате по умолчанию либо выбрать другой формат, указав его в качестве аргумента. Нам больше не нужно запоминать команды вроде tar -czf или zip -r.
Временная метка в имени архива предотвращает перезапись предыдущих архивов, что делает этот подход идеальным для быстрого создания снимков перед важными изменениями.
#5. Быстрый поиск больших файлов
Со временем дисковое пространство заполняется по мере накопления больших файлов — старые резервные копии, логи, образы виртуальных машин и архивы могут незаметно занять гигабайты.
Один из самых быстрых способов понять, в чем проблема, — использовать find, чтобы определить, что именно занимает место в дереве каталогов. Но синтаксис этой команды не всегда легко запомнить.
#!/usr/bin/env bash
# findlarge — find the largest files under a path
# Usage: findlarge [directory] [min_size_MB] [count]
set -euo pipefail
DIR="${1:-.}"
MIN_MB="${2:-100}"
COUNT="${3:-20}"
echo "Finding files larger than ${MIN_MB}MB under ${DIR} ..."
echo ""
find "$DIR" -type f -size +"${MIN_MB}M" -printf '%s\t%p\n' 2>/dev/null \
| sort -rn \
| head -"$COUNT" \
| awk '{
size=$1
path=$2
if (size >= 1073741824)
printf " %7.2f GB %s\n", size/1073741824, path
else
printf " %7.2f MB %s\n", size/1048576, path
}'# Usage: findlarge /var 50 10 # top 10 files >50MB under /var findlarge /home 200 # default top 20, >200MB, under /home findlarge # top 20 files >100MB in current directory
Этот скрипт позволяет легко находить большие файлы при очистке дискового пространства или поиске того, что занимает место на диске. Использование параметра -printf команды find выводит размеры файлов в байтах, что удобно для сортировки и надежнее, чем разбирать размеры в человекочитаемом формате.
#6. Краткий обзор состояния системы
Первое, что нам нужно выполнить на любой незнакомой машине или в любой момент, когда что-то работает не так, — это проверить её текущее состояние: время работы, среднюю нагрузку, давление на память, использование диска и процессы с наибольшим потреблением CPU, объединив все это в единый, легко читаемый отчет.
Запуск каждой команды отдельно работает, но это занимает время и требует помнить несколько команд.
#!/usr/bin/env bash
# sysbrief — quick system health snapshot
set -euo pipefail
BOLD='\033[1m'
RESET='\033[0m'
RED='\033[0;31m'
YELLOW='\033[0;33m'
GREEN='\033[0;32m'
section() { echo -e "\n${BOLD}── $1 ──${RESET}"; }
section "System Information"
echo "Host : $(hostname)"
echo "Kernel : $(uname -r)"
section "Uptime & Load"
uptime -p
awk '{printf "Load avg: %.2f %.2f %.2f\n", $1, $2, $3}' /proc/loadavg
section "Memory"
free -h | awk 'NR==2 {
used=$3; total=$2; avail=$7
printf "Used: %s / %s | Available: %s\n", used, total, avail
}'
section "Disk Usage (>70%)"
df -h --output=target,pcent,size,avail | awk 'NR==1 || $2+0 > 70 {
if (NR==1) print; else print "\033[0;33m" $0 "\033[0m"
}'
section "Top 5 CPU Consumers"
ps -eo pid,comm,%cpu,%mem --sort=-%cpu | head -6
section "Swap"
swapon --show 2>/dev/null || echo "No swap configured"sysbrief
Вместо запуска нескольких команд, таких как uptime, df -h и free -h, нам нужна только одна команда, чтобы получить быстрый обзор нашей системы. Она особенно полезна при устранении проблем или проверке состояния сервера.
How I Troubleshoot Linux in Production Without Taking Servers Down
Перестаньте перезагружаться. Вот что следует проверить в первую очередь.
#7. Удаление дубликатов файлов в каталоге
Наличие дубликатов файлов — обычное явление, особенно после многократной загрузки одного и того же файла, копирования папок проекта или объединения резервных копий. Со временем они занимают место на диске и усложняют организацию каталогов.
Поиск дубликатов вручную выполняется медленно и часто приводит к ошибкам, особенно в больших каталогах, где многие файлы могут иметь похожие имена или содержимое.
#!/usr/bin/env bash
# rmdup — find (and optionally remove) duplicate files
# Usage: rmdup [directory] [--delete]
set -euo pipefail
DIR="${1:-.}"
DELETE="${2:-}"
echo "Scanning for duplicates in: $DIR"
echo ""
declare -A SEEN
DUPES=()
while IFS= read -r -d '' file; do
hash=$(md5sum "$file" | cut -d' ' -f1)
if [[ -n "${SEEN[$hash]:-}" ]]; then
DUPES+=("$file")
echo " DUP $file"
echo " OF ${SEEN[$hash]}"
echo ""
else
SEEN[$hash]="$file"
fi
done < <(find "$DIR" -maxdepth 1 -type f -print0 | sort -z)
if [[ ${#DUPES[@]} -eq 0 ]]; then
echo "No duplicates found."
exit 0
fi
echo "Found ${#DUPES[@]} duplicate(s)."
if [[ "$DELETE" == "--delete" ]]; then
for f in "${DUPES[@]}"; do
rm -v "$f"
done
echo "Deleted ${#DUPES[@]} duplicate(s)."
else
echo "Run with --delete to remove duplicates."
fi# Usage: rmdup ~/Downloads # show duplicates only rmdup ~/Downloads --delete # show and delete duplicates
Вместо ручного сравнения файлов rmdup сравнивает контрольную сумму каждого файла, чтобы найти файлы с одинаковым содержимым. Он явно показывает, какой файл является дубликатом другого, что позволяет легко проверить результаты перед выполнением каких-либо действий.
По умолчанию он только показывает список дубликатов, а для их удаления необходимо использовать --delete, что делает запуск более безопасным.
#8. Мониторинг нескольких сервисов
При устранении проблем в системе нам часто требуется одновременно отслеживать логи нескольких сервисов. Например, мы можем захотеть наблюдать логи Nginx, Docker и нашего приложения.
Запуск отдельных команд journalctl -f в разных терминалах работает, но быстрое переключение между окнами становится неудобным.
#!/usr/bin/env bash
# journalwatch — monitor multiple services with color-coded output
# Usage: journalwatch nginx [...]
set -euo pipefail
services=("$@")
if [ $# -eq 0 ]; then
echo "Usage: journalwatch <service> [service ...]"
exit 1
fi
colors=(
"\033[31m"
"\033[32m"
"\033[33m"
"\033[34m"
"\033[35m"
)
reset="\033[0m"
for i in "${!services[@]}"; do
service="${services[$i]}"
color="${colors[$((i % ${#colors[@]}))]}"
journalctl -fu "$service" |
while IFS= read -r line; do
printf "${color}[%s]${reset} %s\n" "$service" "$line"
done &
done
waitjournalwatch nginx docker myapp
Вместо открытия нескольких терминалов мы можем отслеживать несколько сервисов systemd из одного окна. Цветные имена сервисов позволяют легко увидеть, какой сервис создал каждую запись в логах, что значительно упрощает устранение проблем.
Примечание:
Этот скрипт используетjournalctl, поэтому он работает в Linux-системах, использующих systemd. Для просмотра логов некоторых сервисов может потребоватьсяsudo.
Journalctl: Diagnosing Linux issues the right way
LINUX | BASH | SYSADMIN | DEVOPS | PROGRAMMING Journalctl: Правильная диагностика проблем в Linux: перестаньте перезагружать свой…
#9. Сводка Git-репозитория
При работе с Git-репозиторием мы часто выполняем несколько команд только для того, чтобы понять, что происходит. Мы можем посмотреть текущую ветку, проверить наличие незакоммиченных изменений, просмотреть последние коммиты или проверить, находится ли наша ветка впереди или позади удалённой ветки.
Запуск каждой команды отдельно работает, но быстро становится повторяющимся.
#!/usr/bin/env bash
# gitsum — git repo status summary
set -euo pipefail
BOLD='\033[1m'
CYAN='\033[0;36m'
YELLOW='\033[0;33m'
GREEN='\033[0;32m'
RESET='\033[0m'
if ! git rev-parse --is-inside-work-tree &>/dev/null; then
echo "Not inside a git repository." >&2
exit 1
fi
ROOT=$(git rev-parse --show-toplevel)
BRANCH=$(git symbolic-ref --short HEAD 2>/dev/null || git rev-parse --short HEAD)
REMOTE=$(git remote 2>/dev/null | head -1)
echo -e "${BOLD}Repository:${RESET} $(basename "$ROOT")"
echo -e "${BOLD}Branch:${RESET} ${CYAN}${BRANCH}${RESET}"
# Ahead/behind tracking
if [[ -n "$REMOTE" ]]; then
TRACKING=$(git for-each-ref --format='%(upstream:short)' "$(git symbolic-ref HEAD 2>/dev/null)" 2>/dev/null)
if [[ -n "$TRACKING" ]]; then
AHEAD=$(git rev-list "${TRACKING}..HEAD" --count 2>/dev/null || echo 0)
BEHIND=$(git rev-list "HEAD..${TRACKING}" --count 2>/dev/null || echo 0)
echo -e "${BOLD}Remote:${RESET} ${REMOTE} (↑${AHEAD} ↓${BEHIND})"
fi
fi
echo ""
echo -e "${BOLD}Working tree:${RESET}"
STATUS=$(git status --short)
if [[ -z "$STATUS" ]]; then
echo -e " ${GREEN}Clean${RESET}"
else
echo "$STATUS" | sed 's/^/ /'
fi
echo ""
echo -e "${BOLD}Recent commits:${RESET}"
git log --oneline --graph --decorate -8
echo ""
echo -e "${BOLD}Stash:${RESET} $(git stash list 2>/dev/null | wc -l) entries"gitsum
Вместо запуска git branch, git status, git log, git remote и git stash list отдельно мы можем использовать одну команду, чтобы увидеть текущую ветку, состояние рабочей директории, последние коммиты, количество записей в stash и находится ли ветка впереди или позади удалённой ветки. Это даёт быстрый обзор перед началом работы или отправкой изменений.
Git: Полное руководство для начинающих
Начало работы с Git. Узнайте, как настроить Git, создать коммит, работать с ветками Git и объединять ветки Git.
#10. Проверка записей SSH-конфигурации
При управлении большим количеством удалённых хостов в ~/.ssh/config нам нужно убедиться, что записи доступны и что аутентификация по ключу работает.
Можно вручную пройтись по всем настроенным хостам и проверить их состояние, но это неудобно и занимает много времени.
#!/usr/bin/env bash
# sshcheck — test connectivity to all configured SSH hosts
# Usage: sshcheck [timeout_seconds]
set -euo pipefail
TIMEOUT="${1:-5}"
CONFIG="${HOME}/.ssh/config"
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[0;33m'
RESET='\033[0m'
if [[ ! -f "$CONFIG" ]]; then
echo "No SSH config found at $CONFIG" >&2
exit 1
fi
HOSTS=$(grep -i '^Host ' "$CONFIG" | awk '{print $2}' | grep -v '\*')
echo "Testing SSH hosts (timeout: ${TIMEOUT}s)..."
echo ""
printf " %-30s %s\n" "Host" "Status"
printf " %-30s %s\n" "----" "------"
while IFS= read -r host; do
if ssh -o ConnectTimeout="$TIMEOUT" \
-o BatchMode=yes \
-o StrictHostKeyChecking=no \
"$host" true 2>/dev/null; then
printf " ${GREEN}%-30s ✓ OK${RESET}\n" "$host"
else
EXIT=$?
if [[ $EXIT -eq 255 ]]; then
printf " ${RED}%-30s ✗ Unreachable${RESET}\n" "$host"
else
printf " ${YELLOW}%-30s ⚠ Auth failed (exit $EXIT)${RESET}\n" "$host"
fi
fi
done <<< "$HOSTS"sshcheck # test all hosts, 5s timeout sshcheck 10 # 10s timeout
Вместо подключения к каждому серверу отдельно sshcheck проверяет каждый хост, определённый в ~/.ssh/config, с помощью одной команды. Он быстро показывает, какие серверы доступны, а какие требуют внимания, что делает его удобным инструментом перед развертыванием или регулярным обслуживанием.
SSH (Secure Shell): A Beginner’s Guide
Полное руководство по основам SSH, безопасным соединениям, управлению ключами и передовым методам современной разработки.
#11. Проверка прослушиваемых портов
Одна из самых распространённых ежедневных задач разработчиков — определить, какой процесс владеет портом, особенно когда другой сервис уже использует его до того, как мы запускаем собственный.
Мы можем использовать ss или lsof для этого, но это всё ещё требует ручной проверки и не предоставляет быстрого обзора, из-за чего процесс становится медленным и повторяющимся.
#!/usr/bin/env bash
# portcheck — show listening ports with owning process
# Usage: portcheck [port]
set -euo pipefail
if [[ $# -eq 1 ]]; then
ss -tlnp | awk -v port=":$1" '$4 ~ port || $5 ~ port'
echo ""
echo "Process detail:"
lsof -i :"$1" -nP 2>/dev/null || echo " (lsof unavailable or no match)"
else
echo "All listening TCP/UDP ports:"
echo ""
ss -tulnp | column -t
fiportcheck # all listening ports portcheck 5432 # who owns port 5432
Вместо запоминания разных команд ss и lsof нам нужно только выполнить portcheck. Он быстро показывает, какие порты прослушиваются и, для конкретного порта, какой процесс его использует. Это особенно полезно при проверке корректного запуска сервиса или исследовании конфликтов портов.
#12. Снимок сетевых подключений
При диагностике проблем с подключением или проверке исходящих подключений на сервере мы часто хотим быстро получить ответы: какие удалённые хосты подключены, сколько активных подключений существует и какие сервисы ожидают входящие подключения.
Хотя ss и netstat могут предоставить эту информацию, они выводят необработанные данные вместо понятной сводки.
#!/usr/bin/env bash
# netsnap — summarize active network connections
set -euo pipefail
BOLD='\033[1m'
RESET='\033[0m'
echo -e "${BOLD}Established connections by remote host:${RESET}"
ss -tnp state established \
| awk 'NR>1 {print $4}' \
| sed 's/:[0-9]*$//' \
| sort | uniq -c | sort -rn \
| awk '{printf " %4d %s\n", $1, $2}' \
| head -20
echo ""
echo -e "${BOLD}Connection states summary:${RESET}"
ss -tan \
| awk 'NR>1 {print $1}' \
| sort | uniq -c | sort -rn \
| awk '{printf " %4d %s\n", $1, $2}'
echo ""
echo -e "${BOLD}Listening services (TCP):${RESET}"
ss -tlnp \
| awk 'NR>1 {printf " %-25s %s\n", $4, $NF}'Вместо ручного анализа вывода netsnap предоставляет быстрый обзор сетевой активности нашей системы одной командой. Это удобный способ увидеть активные подключения, состояния подключений и прослушиваемые сервисы при устранении проблем с сетью или приложениями.
Mastering Linux Networking
How to Debug Linux Server Networking Issues
Практический контрольный список для ускорения отладки и снижения уровня разочарования.
#13. Пакетное переименование файлов
Нередко бывает, что появляются десятки файлов с именами IMG_20240101_*.jpg, которые нужно переименовать в vacation_*.jpg, или требуется удалить пробелы из каждого имени файла в каталоге.
Переименование файлов вручную непрактично, когда нужно обновить десятки или сотни имён.
#!/usr/bin/env bash
# rename-batch — bulk rename files using find-and-replace on filenames
# Usage: rename-batch <find> <replace> [directory]
set -euo pipefail
FIND="${1:-}"
REPLACE="${2:-}"
DIR="${3:-.}"
if [[ -z "$FIND" || -z "$REPLACE" ]]; then
echo "Usage: rename-batch <find> <replace> [directory]" >&2
echo " Replaces all occurrences of <find> in filenames under [directory]" >&2
echo " Example: rename-batch ' ' '_' ./downloads" >&2
exit 1
fi
COUNT=0
while IFS= read -r -d '' file; do
dir=$(dirname "$file")
base=$(basename "$file")
newbase="${base//"$FIND"/"$REPLACE"}"
if [[ "$base" != "$newbase" ]]; then
mv -- "$file" "$dir/$newbase"
echo " $base → $newbase"
(( COUNT++ ))
fi
done < <(find "$DIR" -maxdepth 1 -type f -print0 | sort -z)
echo ""
echo "Renamed $COUNT file(s)."rename-batch ' ' '_' ~/Downloads # spaces → underscores rename-batch 'IMG_' 'photo_' ./ # prefix swap rename-batch '.JPEG' '.jpg' ./photos # extension normalization
Вместо редактирования каждого имени файла вручную мы можем применить операцию поиска и замены ко всем подходящим файлам. Это делает переименование быстрее, проще и безопаснее, поскольку оно затрагивает только файлы в выбранном каталоге.
Вывод: Простые скрипты, решающие повседневные проблемы, зачастую оказываются наиболее ценными.
Shell-скрипты не обязательно должны означать написание сотен строк кода. Многие самые полезные скрипты — это небольшие утилиты, которые решают повседневные задачи. Они устраняют повторяющуюся работу, уменьшают количество ошибок и позволяют сосредоточиться на настоящем решении проблем вместо повторения одних и тех же команд.
Когда вы сталкиваетесь с повторяющимися задачами, спросите себя: «Могу ли я превратить это в скрипт?» Со временем эти небольшие скрипты накапливаются — они экономят вам секунды здесь, предотвращают ошибки там и делают работу в терминале более удобной.
Скрипты в этой статье не предназначены быть идеальными или полностью функциональными. Думайте о них как о начальных вариантах, которые мы можем настроить под собственный сценарий работы.
Спасибо за чтение! Надеюсь, эта статья станет отправной точкой для создания собственных инструментов и повышения вашей продуктивности.
На этом все! Спасибо за внимание! Если статья была интересна, подпишитесь на телеграм-канал usr_bin, где будет еще больше полезной информации.