blog
2026-10-05
0 阅读
Ubuntu26.04 nautilus右键图片转换到avif脚本
把脚本放到以下路径,不要有扩展名:
~/.local/share/nautilus/scripts/Conver2AVIF
#!/bin/bash
# ============================================================
# Nautilus 右键传入的文件/目录
# ============================================================
SELECTED_ITEMS=("$@")
FORMATS="jpg,jpeg,png,webp,gif,tiff,bmp"
QUALITY=70
PARALLEL=1
MAX_SIZE_MB=200
REPORT_FILE="avif_report.md"
RETRY_FILE="avif_retry.list"
# ============================================================
# 自动安装依赖
# ============================================================
install_dependencies() {
if command -v magick >/dev/null 2>&1; then
CONVERTER="magick"
return
fi
if command -v avifenc >/dev/null 2>&1; then
CONVERTER="avifenc"
return
fi
if [[ -f /etc/debian_version ]]; then
sudo apt update && sudo apt install -y imagemagick
else
zenity --error --text="请手动安装 ImageMagick 或 avifenc"
exit 1
fi
if command -v magick >/dev/null 2>&1; then
CONVERTER="magick"
else
zenity --error --text="ImageMagick 安装失败"
exit 1
fi
}
install_dependencies
# ============================================================
# 收集所有文件(递归所有子目录 + 支持直接选图片)
# ============================================================
FILES=()
IFS=',' read -ra EXT_LIST "$REPORT_FILE"
echo "| 原文件 | 原大小 | AVIF大小 | 压缩率 | 状态 |" >> "$REPORT_FILE"
echo "|--------|--------|----------|--------|--------|" >> "$REPORT_FILE"
# ============================================================
# 转换函数(关键:每张图用自己的目录建 avif/)
# ============================================================
convert_one() {
local img="$1"
local dir="$(dirname "$img")"
local filename="$(basename "$img")"
# 每个目录单独一个 avif 子目录
local output_dir="$dir/avif"
mkdir -p "$output_dir"
local output="$output_dir/${filename%.*}.avif"
if [[ -f "$output" ]]; then
echo "跳过已存在: $output"
return
fi
local size_mb
size_mb=$(du -m "$img" | cut -f1)
if (( size_mb > MAX_SIZE_MB )); then
echo "跳过过大文件 ($size_mb MB): $img"
return
fi
local before_size
before_size=$(du -h "$img" | cut -f1)
if [[ "$CONVERTER" == "magick" ]]; then
magick "$img" -quality "$QUALITY" "$output"
else
avifenc --min 0 --max "$QUALITY" "$img" "$output"
fi
if [[ $? -ne 0 ]]; then
echo "转换失败: $img"
echo "$img" >> "$RETRY_FILE"
echo "| $filename | $before_size | - | - | ❌失败 |" >> "$REPORT_FILE"
return
fi
local after_size
after_size=$(du -h "$output" | cut -f1)
local before_k
before_k=$(du -k "$img" | cut -f1)
local after_k
after_k=$(du -k "$output" | cut -f1)
local ratio=$(( 100 * after_k / before_k ))
echo "| $filename | $before_size | $after_size | ${ratio}% | ✅成功 |" >> "$REPORT_FILE"
}
export -f convert_one
export CONVERTER QUALITY MAX_SIZE_MB REPORT_FILE RETRY_FILE
# ============================================================
# 并行执行
# ============================================================
printf "%s\n" "${FILES[@]}" | xargs -I {} -P "$PARALLEL" bash -c 'convert_one "$@"' _ {}
zenity --info --text="AVIF 转换完成,共处理 $TOTAL 个文件。各目录已生成各自的 avif/ 子目录。"