Конвертировать изображения в WebP с помощью сценария Nautilus в Linux

Для веба почти всегда нужен WebP: меньше весит при той же картинке, страницы грузятся быстрее. Беру JPG, PNG, GIF, HEIC и ещё несколько форматов, конвертирую в WebP с качеством 85%. В скрипте если файлов много — будет показываться прогресс-бар.

Куда положить

Можно просто скачать скрипт Nautilus ниже и положить по этому пути. Скрипты Nautilus живут здесь:

bash
~/.local/share/nautilus/scripts/

Этот файл — ~/.local/share/nautilus/scripts/Конвертировать в WebP. В свойствах включаю «Исполняемый как приложение» — без этого пункта в меню не будет.

Или через командную строку

  1. Ставлю зависимости

    Скрипт проверяет команду convert из ImageMagick и пользуется zenity для прогресса и отчёта. На свежих Ubuntu вместо convert иногда magick — тот же пакет. pip, cwebp и libheif-examples не нужны: HEIC тоже идёт через convert.

    bash
    sudo apt install -y imagemagick zenity
  2. Создаю файл

    Имя файла — то, что будет в меню: Конвертировать в WebP.

    bash
    mkdir -p ~/.local/share/nautilus/scripts
    touch ~/.local/share/nautilus/scripts/"Конвертировать в WebP"
  3. Даю права на исполнение

    Без бита исполнения Nautilus скрипт не покажет.

    bash
    chmod +x ~/.local/share/nautilus/scripts/"Конвертировать в WebP"
  4. Открываю в редакторе

    xdg-open поднимает графический редактор, не nano.

    bash
    xdg-open ~/.local/share/nautilus/scripts/"Конвертировать в WebP"
  5. Вставляю код и пользуюсь

    Вставляю код ниже и пользуюсь: выделил файлы → ПКМ → «Сценарии». Чтобы меню подхватило файл:

    bash
    nautilus -q

Код

bash
#!/bin/bash

readonly WEBP_QUALITY=85
readonly SCRIPT_TITLE="Конвертировать в WebP"

declare -i converted=0 skipped=0 failed=0
report_lines=()

require_imagemagick() {
    if command -v convert >/dev/null 2>&1; then
        return 0
    fi

    zenity --error --no-wrap 
        --title="$SCRIPT_TITLE" 
        --text=$'Нужен ImageMagick.nnsudo apt install imagemagick'
    exit 1
}

gather_selection() {
    local -n _out=$1

    if [ -n "${NAUTILUS_SCRIPT_SELECTED_FILE_PATHS:-}" ]; then
        IFS=$'n' read -d '' -r -a _out < <(printf '%sn' "$NAUTILUS_SCRIPT_SELECTED_FILE_PATHS")
        return
    fi

    if [ "$#" -gt 0 ]; then
        _out=("$@")
        return
    fi

    zenity --error --no-wrap --title="$SCRIPT_TITLE" --text="Сначала выделите изображения."
    exit 1
}

file_extension_lower() {
    local path="$1"
    local ext="${path##*.}"

    if [ "$ext" = "$path" ]; then
        printf ''
        return
    fi

    printf '%s' "${ext,,}"
}

is_supported_image() {
    case "$1" in
        jpg|jpeg|jpe|jfif|png|bmp|tif|tiff|gif|heic|heif|heics)
            return 0
            ;;
        *)
            return 1
            ;;
    esac
}

source_for_imagemagick() {
    case "$1" in
        heic|heif|heics)
            printf '%s[0]' "$2"
            ;;
        *)
            printf '%s' "$2"
            ;;
    esac
}

add_report_line() {
    report_lines+=("$1")
}

process_image() {
    local path="$1"
    local ext output input_for_magick base

    if [ ! -f "$path" ]; then
        skipped=$((skipped + 1))
        add_report_line "⊘ не найден: $(basename "$path")"
        return
    fi

    ext=$(file_extension_lower "$path")
    base=$(basename "$path")
    output="${path%.*}.webp"

    if [ -z "$ext" ]; then
        skipped=$((skipped + 1))
        add_report_line "⊘ без расширения: $base"
        return
    fi

    if [ "$ext" = "webp" ]; then
        skipped=$((skipped + 1))
        add_report_line "⊘ уже WebP: $base"
        return
    fi

    if ! is_supported_image "$ext"; then
        skipped=$((skipped + 1))
        add_report_line "⊘ формат .$ext: $base"
        return
    fi

    input_for_magick=$(source_for_imagemagick "$ext" "$path")

    if convert "$input_for_magick" -auto-orient -quality "$WEBP_QUALITY" "$output"; then
        converted=$((converted + 1))
        add_report_line "✓ $base"
    else
        failed=$((failed + 1))
        add_report_line "✗ сбой: $base"
        rm -f -- "$output"
    fi
}

show_progress() {
    local total="$1"
    shift
    local items=("$@")
    local index=0
    local percent=0

    for file in "${items[@]}"; do
        index=$((index + 1))
        percent=$((index * 100 / total))
        printf '%sn# %sn' "$percent" "$(basename "$file")"
        process_image "$file"
    done | zenity --progress 
        --title="$SCRIPT_TITLE" 
        --text="Обработка файлов…" 
        --percentage=0 
        --auto-close 
        --auto-kill
}

build_final_message() {
    local message=""

    message="Готово: ${converted} из $((${converted} + ${skipped} + ${failed}))"
    message+="nПропущено: ${skipped}"

    if [ "${failed}" -gt 0 ]; then
        message+="nС ошибкой: ${failed}"
    fi

    if [ "${#report_lines[@]}" -gt 0 ]; then
        message+="nn$(printf '%sn' "${report_lines[@]}")"
    fi

    printf '%s' "$message"
}

notify_result() {
    local message="$1"

    if [ "${failed}" -gt 0 ]; then
        zenity --error --no-wrap --title="$SCRIPT_TITLE" --text="$message"
        return
    fi

    if [ "${converted}" -eq 0 ]; then
        zenity --warning --no-wrap --title="$SCRIPT_TITLE" --text="$message"
        return
    fi

    zenity --info --no-wrap --title="$SCRIPT_TITLE" --text="$message"
}

require_imagemagick

selected=()
gather_selection selected "$@"

count=${#selected[@]}
if [ "$count" -eq 0 ]; then
    zenity --error --no-wrap --title="$SCRIPT_TITLE" --text="Список файлов пуст."
    exit 1
fi

if [ "$count" -eq 1 ]; then
    process_image "${selected[0]}"
else
    show_progress "$count" "${selected[@]}"
fi

notify_result "$(build_final_message)"
← К списку статей

Поделиться

Комментарии

Пока нет комментариев — можете написать первый.

Оставить комментарий

Войти с помощью

или оставьте комментарий как гость

Отправка защищена сервисом Yandex SmartCaptcha. Подробности — в политике конфиденциальности.