Script Launcher
Linux
Скрипты далее перебирают все скрипты *.sh
в каталоге запуска и подкаталогах, если имеет доступ
и отбирают те в которых есть # ==AUTOEXEC==
#!/bin/bash
# ==AUTOEXEC==
# === Название программы ===
# * Строка для основного описания
# * Строки для развернутого описания
# * Строки для развернутого описания
# //строка ниже служит для обозначения окончания описания
#
признаком окончания описания является первая первая найденная строка где кроме #
ничего нет
Шаблон скрипта
Шаблон оформления скрипта для применения в лаунчере
Дополнительно сделан шаблон меню с выбором пунктов
Шаблон файла с заголовками для использования в лаунчере (нажмите чтобы раскрыть)
- template.sh
#!/bin/bash
# ==AUTOEXEC==
# === Шаблон меню для нового скрипта ===
# * Основной шаблон bash-скрипта с пунктами меню и выходом по 0
# * Добавьте сюда свои действия и команды
# * Автор:
# * Дата
#
PS3="📌 Выберите действие: "
echo " 0) ❌ Выход"
select action in "📂 Действие 1" "⚙️ Действие 2" "❌ Выход"; do
if [[ "$REPLY" == "0" ]]; then
echo "👋 До свидания!"
exit 0
fi
case $REPLY in
1)
echo "👉 Выполняем Действие 1"
# ваша команда здесь
;;
2)
echo "🔧 Выполняем Действие 2"
# ваша команда здесь
;;
3)
echo "👋 До свидания!"
exit 0
;;
*)
echo "❗ Неверный выбор";;
esac
break
done
exit 0
Лаунчер скриптов (с оболочкой fzf)
При запуске можно выбрать fzf меню или средствами bash скрипта
Еслы был выбор fzf но он не установлен, запустится выбор через bash скрипт
Скрипт для поиска и запуска скрптов из подкаталогов при помощи утилиты fzf (нажмите чтобы раскрыть)
- launcher_fzf.sh
#!/bin/bash
export LANG=en_US.UTF-8
export LC_ALL=en_US.UTF-8
INCLUDE_MARKER="# ==AUTOEXEC=="
ROOT_DIR="$(pwd)"
TMP_LIST="/tmp/script_launcher_list.txt"
SELECTED_FILE=""
# --- Проверка fzf ---
HAS_FZF=false
if command -v fzf &>/dev/null; then
HAS_FZF=true
fi
# --- Сбор скриптов (.sh и .py 'по умолчанию отключено') ---
> "$TMP_LIST"
find "$ROOT_DIR" -type f -name "*.sh" | while read -r FILE; do
if grep -q "^$INCLUDE_MARKER" "$FILE"; then
TITLE=""
SHORT=""
while IFS= read -r line; do
[[ -z "$line" ]] && break
if [[ "$line" =~ ^# ]]; then
CLEANED="${line#\# }"
if [[ "$CLEANED" =~ ^===.*=== ]]; then
TITLE="$CLEANED"
elif [[ "$CLEANED" =~ ^\* ]]; then
SHORT="${CLEANED#\* }"
fi
fi
done < <(tail -n +2 <(grep -A30 "^$INCLUDE_MARKER" "$FILE"))
DISPLAY_LINE="$(basename "$FILE") :: $TITLE * $SHORT"
echo -e "$DISPLAY_LINE|$FILE" >> "$TMP_LIST"
fi
done
if [ ! -s "$TMP_LIST" ]; then
echo "❌ Не найдено подходящих скриптов."
exit 1
fi
# --- Выбор интерфейса запуска ---
while true; do
echo "\n📦 Выберите режим запуска:"
echo " 1) fzf-интерфейс $( [ "$HAS_FZF" = true ] && echo "(доступен)" || echo "(недоступен)" )"
echo " 2) Классическое текстовое меню"
echo " 0) Выход"
echo -n ">> "
read -r launcher_mode
case "$launcher_mode" in
1)
if [ "$HAS_FZF" = true ]; then
SELECTED_LINE=$(cat "$TMP_LIST" | \
fzf --prompt="🚀 Выберите скрипт: " \
--preview='FILE=$(echo {} | cut -d"|" -f2); \
[ -f "$FILE" ] && awk "/^# ==AUTOEXEC==/{flag=1; next} /^$/{flag=0} flag && /^#/ { sub(/^# ?/, \"\", \$0); print }" "$FILE" || echo "❌ Файл не найден: $FILE"' \
--preview-window=right:60%:wrap)
if [ -z "$SELECTED_LINE" ]; then
echo "❎ Отмена пользователем."
rm -f "$TMP_LIST"
exit 0
fi
SELECTED_FILE=$(echo "$SELECTED_LINE" | cut -d'|' -f2)
break
else
echo "⚠️ fzf не установлен. Установите с помощью:"
echo " sudo apt update && sudo apt install -y fzf"
launcher_mode=2
fi
;;
2)
echo "📜 Найденные скрипты:"
echo " 0) ❌ Выход"
echo
mapfile -t ENTRIES < <(cut -d'|' -f1 "$TMP_LIST")
ENTRIES+=("❌ Выход")
PS3="📌 Выберите скрипт: "
select ENTRY in "${ENTRIES[@]}"; do
if [[ "$REPLY" == "0" || "$ENTRY" == "❌ Выход" ]]; then
echo "👋 До свидания!"; rm -f "$TMP_LIST"; exit 0
fi
[ -z "$ENTRY" ] && echo "❌ Неверный выбор" && continue
SELECTED_FILE=$(grep -F "$ENTRY" "$TMP_LIST" | head -n1 | cut -d'|' -f2)
break 2
done
;;
0)
echo "👋 До свидания!"
rm -f "$TMP_LIST"
exit 0
;;
*)
echo "❌ Неверный выбор"
;;
esac
done
# --- Подтверждение и запуск ---
echo "\n⚠️ Скрипт: $SELECTED_FILE"
echo "Запустить его? (y/N):"
read -r confirm
if [[ "$confirm" =~ ^[Yy]$ ]]; then
echo "🚀 Запуск..."
EXT="${SELECTED_FILE##*.}"
case "$EXT" in
sh) bash "$SELECTED_FILE" ;;
# py) python3 "$SELECTED_FILE" ;;
*) echo "❌ Неизвестный тип файла: $EXT" ;;
esac
else
echo "❎ Отмена."
fi
rm -f "$TMP_LIST"
Ver 2
Лаунчер
- launcher.sh
#!/bin/bash
# Устанавливаем локаль, чтобы fzf и вывод работали корректно
export LANG=en_US.UTF-8
export LC_ALL=en_US.UTF-8
# Маркер, по которому определяется, что скрипт можно запускать из меню
INCLUDE_MARKER="# ==AUTOEXEC=="
# Текущий рабочий каталог, откуда начнётся поиск
ROOT_DIR="$(pwd)"
# Создаём уникальный временный файл для хранения списка скриптов
TMP_LIST=$(mktemp /tmp/script_launcher_list.XXXXXX)
# Удалим временный файл при завершении скрипта — в любом случае
trap "rm -f '$TMP_LIST'" EXIT
# Переменная для хранения выбранного файла
SELECTED_FILE=""
# --- Проверка наличия fzf ---
HAS_FZF=false
if command -v fzf &>/dev/null; then
HAS_FZF=true
fi
# --- Сбор скриптов (.sh; поддержка .py отключена по умолчанию) ---
> "$TMP_LIST"
find "$ROOT_DIR" -type f -name "*.sh" | while read -r FILE; do
if grep -q "^$INCLUDE_MARKER" "$FILE"; then
TITLE=""
SHORT=""
# Чтение заголовка и краткого описания из комментариев после маркера
while IFS= read -r line; do
[[ -z "$line" ]] && break
if [[ "$line" =~ ^# ]]; then
CLEANED="${line#\# }"
if [[ "$CLEANED" =~ ^===.*=== ]]; then
TITLE="$CLEANED"
elif [[ "$CLEANED" =~ ^\* ]]; then
SHORT="${CLEANED#\* }"
fi
fi
done < <(tail -n +2 <(grep -A30 "^$INCLUDE_MARKER" "$FILE"))
DISPLAY_LINE="$(basename "$FILE") :: $TITLE * $SHORT"
echo -e "$DISPLAY_LINE|$FILE" >> "$TMP_LIST"
fi
done
# Если список скриптов пуст — выходим
if [ ! -s "$TMP_LIST" ]; then
echo "❌ Не найдено подходящих скриптов."
exit 1
fi
# --- Выбор интерфейса запуска ---
while true; do
echo -e "\n📦 Выберите режим запуска:"
echo " 1) fzf-интерфейс $( [ "$HAS_FZF" = true ] && echo "(доступен)" || echo "(недоступен)" )"
echo " 2) Классическое текстовое меню"
echo " 0) Выход"
echo -n ">> "
read -r launcher_mode
case "$launcher_mode" in
1)
if [ "$HAS_FZF" = true ]; then
# fzf с предпросмотром описания из скрипта
SELECTED_LINE=$(cat "$TMP_LIST" | \
fzf --prompt="🚀 Выберите скрипт: " \
--preview='FILE=$(echo {} | cut -d"|" -f2); \
[ -f "$FILE" ] && awk "/^# ==AUTOEXEC==/{flag=1; next} /^$/{flag=0} flag && /^#/ { sub(/^# ?/, \"\", \$0); print }" "$FILE" || echo "❌ Файл не найден: $FILE"' \
--preview-window=right:60%:wrap)
# Отмена выбора
if [ -z "$SELECTED_LINE" ]; then
echo "❎ Отмена пользователем."
exit 0
fi
SELECTED_FILE=$(echo "$SELECTED_LINE" | cut -d'|' -f2)
break
else
echo "⚠️ fzf не установлен. Установите с помощью:"
echo " sudo apt update && sudo apt install -y fzf"
launcher_mode=2
fi
;;
2)
echo "📜 Найденные скрипты:"
echo " 0) ❌ Выход"
echo
mapfile -t ENTRIES < <(cut -d'|' -f1 "$TMP_LIST")
ENTRIES+=("❌ Выход")
PS3="📌 Выберите скрипт: "
select ENTRY in "${ENTRIES[@]}"; do
if [[ "$REPLY" == "0" || "$ENTRY" == "❌ Выход" ]]; then
echo "👋 До свидания!"
exit 0
fi
[ -z "$ENTRY" ] && echo "❌ Неверный выбор" && continue
SELECTED_FILE=$(grep -F "$ENTRY" "$TMP_LIST" | head -n1 | cut -d'|' -f2)
break 2
done
;;
0)
echo "👋 До свидания!"
exit 0
;;
*)
echo "❌ Неверный выбор"
;;
esac
done
# --- Подтверждение и запуск ---
echo -e "\n⚠️ Скрипт: $SELECTED_FILE"
echo "Запустить его? (y/N):"
read -r confirm
if [[ "$confirm" =~ ^[Yy]$ ]]; then
echo "🚀 Запуск..."
EXT="${SELECTED_FILE##*.}"
case "$EXT" in
sh) bash "$SELECTED_FILE" ;;
# py) python3 "$SELECTED_FILE" ;; # Отключено по умолчанию
*) echo "❌ Неизвестный тип файла: $EXT" ;;
esac
else
echo "❎ Отмена."
fi
Описание
# Script Launcher
Утилита для запуска локальных скриптов с использованием системы тегов и интерфейса выбора. Поддерживает интерактивный выбор через `fzf` (если установлен) или текстовое меню. Разрабатывается для работы в рамках одного каталога, ориентирована на читаемость и безопасность.
---
## 📦 Возможности
- Поиск всех `.sh`-файлов в текущем каталоге
- Отбор скриптов только с маркером `# ==AUTOEXEC==`
- Чтение заголовка (вида `# === Название ===`) и краткого описания (`# * краткое описание`)
- Поддержка интерфейса выбора через `fzf` с предпросмотром описания
- Альтернатива — классическое текстовое меню Bash
- Подтверждение перед запуском
- Поддержка временных файлов через `mktemp` с автоудалением (`trap`)
---
## 🔧 Требования
- Bash 4+
- [fzf](https://github.com/junegunn/fzf) (опционально, для интерактивного режима)
Установка fzf:
```bash
sudo apt update && sudo apt install -y fzf
```
---
## 🧠 Структура
Скрипты должны содержать специальную метку `# ==AUTOEXEC==`, за которой идут комментарии с описанием:
```bash
# ==AUTOEXEC==
# === Название скрипта ===
# * Краткое описание или цель
```
Пример:
```bash
# ==AUTOEXEC==
# === Сохранить резервную копию ===
# * Создаёт .tar.gz архив с логированием
```
---
## 🚀 Запуск
Сначала выполните `launcher.sh` из нужного каталога:
```bash
bash launcher.sh
```
- У меня настроен алиас на высов скрипта 'lll', мне кажется так удобнее
Выберите интерфейс:
1. fzf-интерфейс (если доступен)
2. Классическое меню
0. Выход
Выбранный скрипт запускается **только после подтверждения**.
---
## 🔐 Безопасность и устойчивость
- Временные файлы создаются через `mktemp`, исключая конфликты при параллельном запуске
- Удаляются автоматически через `trap EXIT`
- Нет выполнения кода без согласия пользователя
- Нет внешних сетевых обращений
---
## 📁 Планы на будущее
- Опциональная поддержка `.py`-файлов
- Флаги запуска (`--py`, `--no-preview` и т.п.)
- Категории или теги
- Логирование запусков
---
Дата обновления: 26.03.2025