===== Script Launcher ===== **Linux** Скрипты далее перебирают все скрипты ''*.sh'' в каталоге запуска и подкаталогах, если имеет доступ и отбирают те в которых есть ''# ==AUTOEXEC=='' #!/bin/bash # ==AUTOEXEC== # === Название программы === # * Строка для основного описания # * Строки для развернутого описания # * Строки для развернутого описания # //строка ниже служит для обозначения окончания описания # признаком окончания описания является первая первая найденная строка где кроме ''#'' ничего нет ==== Шаблон скрипта ==== Шаблон оформления скрипта для применения в лаунчере\\ Дополнительно сделан шаблон меню с выбором пунктов ++++Шаблон файла с заголовками для использования в лаунчере (нажмите чтобы раскрыть)| #!/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 (нажмите чтобы раскрыть)| #!/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 ===== ++++Лаунчер| #!/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