侧边栏壁纸
博主头像
可乐呢o3o博主等级

少些比较,多些谦虚。

  • 累计撰写 54 篇文章
  • 累计创建 67 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

Linux AppImage安裝方法,新增开始菜单

Evan
2025-06-14 / 0 评论 / 0 点赞 / 12 阅读 / 6357 字

Debian下使用AppImage创建图标问题

用起来不是很方便,于是写了个脚本帮忙添加到开始菜单:

#!/bin/bash

# 配置变量
ICONS_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/icons"
APPLICATIONS_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/applications"
ICON_SIZES=("256x256" "128x128" "64x64" "48x48" "32x32")
DEFAULT_ICON="application-x-executable"
DEFAULT_CATEGORY="Utility"
REFRESH_DELAY=2     # 刷新延迟时间(秒)
NEEDS_REFRESH=false # 是否需要刷新标志
BATCH_MODE=false    # 批量模式标志

# 日志函数
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
}

error() {
    log "错误: $1" >&2
    exit 1
}

# 检查命令是否存在
check_command() {
    if ! command -v "$1" >/dev/null 2>&1; then
        error "未找到命令: $1"
    fi
}

# 检查必要的命令
check_command update-desktop-database
check_command gtk-update-icon-cache

# 显示帮助信息
show_help() {
    echo "AppImage 安装器"
    echo "使用方法: $0 [选项] <AppImage文件路径或目录>"
    echo ""
    echo "选项:"
    echo "  -h, --help     显示此帮助信息"
    echo "  -u, --uninstall 卸载指定的 AppImage"
    echo "  -f, --force    强制安装/卸载"
    echo "  -v, --verbose  显示详细信息"
    echo "  -d, --delay    设置刷新延迟时间(秒)"
    echo "  -b, --batch    批量安装模式"
    echo ""
    echo "示例:"
    echo "  $0 ./myapp.AppImage     # 安装单个 AppImage"
    echo "  $0 -b ./appimages/      # 批量安装目录下的所有 AppImage"
    echo "  $0 -u myapp             # 卸载 AppImage"
    echo "  $0 -d 5 ./myapp.AppImage # 设置5秒延迟刷新"
}

# 解析命令行参数
UNINSTALL=false
FORCE=false
VERBOSE=false

while [[ $# -gt 0 ]]; do
    case $1 in
    -h | --help)
        show_help
        exit 0
        ;;
    -u | --uninstall)
        UNINSTALL=true
        shift
        ;;
    -f | --force)
        FORCE=true
        shift
        ;;
    -v | --verbose)
        VERBOSE=true
        shift
        ;;
    -d | --delay)
        REFRESH_DELAY="$2"
        shift 2
        ;;
    -b | --batch)
        BATCH_MODE=true
        shift
        ;;
    *)
        APPIMAGE_PATH="$1"
        shift
        ;;
    esac
done

# 检查是否提供了参数
if [ -z "$APPIMAGE_PATH" ]; then
    show_help
    error "未提供 AppImage 文件路径或目录"
fi

# 获取绝对路径
APPIMAGE_PATH=$(realpath "$APPIMAGE_PATH")

# 如果是卸载模式
if [ "$UNINSTALL" = true ]; then
    APP_NAME="$APPIMAGE_PATH"
    if [ -f "$APPLICATIONS_DIR/$APP_NAME.desktop" ]; then
        log "正在卸载 $APP_NAME..."
        rm -f "$APPLICATIONS_DIR/$APP_NAME.desktop"
        rm -f "$ICONS_DIR/$APP_NAME.png"
        NEEDS_REFRESH=true
        log "卸载完成!"
    else
        error "未找到应用程序: $APP_NAME"
    fi
    exit 0
fi

# 安装单个 AppImage 的函数
install_appimage() {
    local appimage_path="$1"
    local app_name=$(basename "$appimage_path" .AppImage)

    # 检查文件是否存在
    if [ ! -f "$appimage_path" ]; then
        log "警告: 文件 '$appimage_path' 不存在,跳过"
        return 1
    fi

    # 检查文件是否为 AppImage
    if [[ ! "$appimage_path" =~ \.AppImage$ ]]; then
        log "警告: 文件 '$appimage_path' 不是 AppImage 格式,跳过"
        return 1
    fi

    # 检查是否已安装
    if [ -f "$APPLICATIONS_DIR/$app_name.desktop" ] && [ "$FORCE" != true ]; then
        log "应用程序 '$app_name' 已安装,跳过"
        return 0
    fi

    # 创建临时目录
    local temp_dir=$(mktemp -d)
    trap 'rm -rf "$temp_dir"' EXIT

    # 提取图标和窗口类名
    log "正在处理 $app_name..."
    cd "$temp_dir"
    "$appimage_path" --appimage-extract >/dev/null 2>&1

    # 尝试从 .desktop 文件中获取窗口类名和类别
    local desktop_file=$(find squashfs-root -name "*.desktop" -type f 2>/dev/null | head -n 1)
    local wm_class=""
    local categories=""

    if [ -n "$desktop_file" ]; then
        wm_class=$(grep -m 1 "StartupWMClass=" "$desktop_file" | cut -d'=' -f2)
        categories=$(grep -m 1 "Categories=" "$desktop_file" | cut -d'=' -f2)
    fi

    if [ -z "$wm_class" ]; then
        wm_class=$(echo "$app_name" | tr '[:upper:]' '[:lower:]')
    fi

    if [ -z "$categories" ]; then
        categories="$DEFAULT_CATEGORY"
    fi

    # 提取图标
    local icon_path=""
    local icon_name="$DEFAULT_ICON"

    # 检查是否已有图标
    if [ -f "$ICONS_DIR/$app_name.png" ] || [ -f "$ICONS_DIR/$app_name.svg" ]; then
        icon_name="$app_name"
    else
        # 搜索所有可能的图标位置
        for base_path in "${ICON_PATHS[@]}"; do
            for size in "${ICON_SIZES[@]}"; do
                path="${base_path/\*/$size}"
                if [ -d "$path" ]; then
                    icon_path=$(find "$path" -name "*.png" -o -name "*.svg" 2>/dev/null | head -n 1)
                    if [ -n "$icon_path" ]; then
                        # 复制图标,使用应用程序名称作为文件名
                        cp "$icon_path" "$ICONS_DIR/$app_name.${icon_path##*.}"
                        icon_name="$app_name"
                        NEEDS_REFRESH=true
                        break 2
                    fi
                fi
            done
        done
    fi

    # 创建桌面入口文件
    log "正在创建桌面入口文件..."
    cat >"$APPLICATIONS_DIR/$app_name.desktop" <<EOF
[Desktop Entry]
Name=$app_name
Exec="$appimage_path" %F
Icon=$icon_name
Terminal=false
Type=Application
Categories=$categories
Comment=$app_name Application
StartupWMClass=$wm_class
MimeType=application/x-executable;
EOF

    # 设置执行权限
    chmod +x "$appimage_path"

    log "完成安装 $app_name"
    return 0
}

# 主安装逻辑
if [ -d "$APPIMAGE_PATH" ]; then
    # 如果是目录,则批量安装
    log "正在扫描目录: $APPIMAGE_PATH"
    find "$APPIMAGE_PATH" -maxdepth 1 -type f -name "*.AppImage" | while read -r appimage; do
        install_appimage "$appimage"
    done
else
    # 如果是单个文件,则安装单个
    install_appimage "$APPIMAGE_PATH"
fi

# 如果需要刷新,则延迟执行
if [ "$NEEDS_REFRESH" = true ]; then
    log "将在 $REFRESH_DELAY 秒后更新桌面数据库..."
    (
        sleep "$REFRESH_DELAY"
        update-desktop-database "$APPLICATIONS_DIR"
        gtk-update-icon-cache -f -t "$ICONS_DIR"
        log "桌面数据库更新完成"
    ) &
fi

log "所有操作完成!"

0

评论区