Last active
August 19, 2025 05:23
-
-
Save kkotaro0111/67462356141b3c008f1609d64ab644fd to your computer and use it in GitHub Desktop.
pngquant / pngopt で指定したフォルダ内のpng画像を再圧縮する
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # エラーが発生した場合、およびパイプラインでエラーが発生した場合にスクリプトを終了する | |
| set -e | |
| set -o pipefail | |
| # --- ヘルプメッセージ --- | |
| usage() { | |
| cat <<EOF | |
| Usage: $(basename "$0") [OPTIONS] <directory> <compression_level> | |
| Re-compresses all PNG files in a directory using pngquant and optipng. | |
| Original files are moved to a subdirectory named '_original'. | |
| Arguments: | |
| <directory> The target directory containing PNG files. | |
| <compression_level> The compression level (1-9, where 9 is maximum compression). | |
| Options: | |
| -n, --dry-run Show what would be done, without actually modifying any files. | |
| -h, --help Display this help message and exit. | |
| EOF | |
| exit 1 | |
| } | |
| # --- 初期値 --- | |
| DRY_RUN=0 | |
| # --- オプション解析 --- | |
| # getoptsではなく、より柔軟なループを使用 | |
| while [[ $# -gt 0 ]]; do | |
| case "$1" in | |
| -n|--dry-run) | |
| DRY_RUN=1 | |
| shift # 引数をシフト | |
| ;; | |
| -h|--help) | |
| usage | |
| ;; | |
| --) | |
| shift # -- の後を引数として扱う | |
| break | |
| ;; | |
| -*) | |
| echo "Unknown option: $1" | |
| usage | |
| ;; | |
| *) | |
| break # オプション以外の引数が見つかったらループを抜ける | |
| ;; | |
| esac | |
| done | |
| # --- 引数のチェック --- | |
| if [ "$#" -ne 2 ]; then | |
| echo "Error: Missing directory or compression level argument." | |
| usage | |
| fi | |
| TARGET_DIR=$1 | |
| COMPRESSION_LEVEL=$2 | |
| COMPRESSED_DIR="$(dirname "$TARGET_DIR")/$(basename "$TARGET_DIR")_compressed" | |
| # --- 依存関係のチェック --- | |
| for cmd in pngquant optipng find mv mkdir basename; do | |
| if ! command -v "$cmd" &> /dev/null; then | |
| echo "Error: Required command '$cmd' is not available in your PATH." | |
| exit 1 | |
| fi | |
| done | |
| # --- 入力値の検証 --- | |
| if [ ! -d "$TARGET_DIR" ]; then | |
| echo "Error: Directory '$TARGET_DIR' not found." | |
| exit 1 | |
| fi | |
| if ! [[ "$COMPRESSION_LEVEL" =~ ^[1-9]$ ]]; then | |
| echo "Error: Compression level must be a number between 1 and 9." | |
| exit 1 | |
| fi | |
| # --- ドライランの表示 --- | |
| if [ "$DRY_RUN" -eq 1 ]; then | |
| echo "*** This is a DRY RUN. No files will be changed. ***" | |
| echo "----------------------------------------------------" | |
| fi | |
| echo "Target directory: $TARGET_DIR" | |
| echo "Compression level: $COMPRESSION_LEVEL" | |
| echo "Compression directory: $COMPRESSED_DIR" | |
| echo "" | |
| # --- 処理の実行 --- | |
| if [ "$DRY_RUN" -eq 0 ]; then | |
| mkdir -p "$COMPRESSED_DIR" | |
| fi | |
| processed_files=0 | |
| # findで見つかったファイルを配列に格納してからループ処理 | |
| mapfile -t -d '' files < <(find "$TARGET_DIR" -type f -iname "*.png" -print0) | |
| for file in "${files[@]}"; do | |
| filename=$(basename "$file") | |
| # 相対パスを取得してサブディレクトリ構造を保持 | |
| relative_path="${file#$TARGET_DIR/}" | |
| convert_file="${COMPRESSED_DIR}/${relative_path}" | |
| working_dir=$(dirname "$convert_file") | |
| if [ "$DRY_RUN" -eq 1 ]; then | |
| echo "[DRY RUN] Would re-compress to '$convert_file' with compression level $COMPRESSION_LEVEL" | |
| else | |
| echo "Processing: $relative_path" | |
| # 1. 作業ディレクトリを作成 | |
| if ! mkdir -p "$working_dir"; then | |
| echo "Error: Failed to create working directory '$working_dir'" | |
| continue | |
| fi | |
| # 2. 再圧縮 (pngquant + optipng) | |
| temp_file="${convert_file}.tmp" | |
| if pngquant --quality=65-80 --output "$temp_file" "$file" 2>/dev/null && \ | |
| optipng -o"$COMPRESSION_LEVEL" -quiet "$temp_file" 2>/dev/null && \ | |
| mv "$temp_file" "$convert_file"; then | |
| echo "✓ Successfully processed: $relative_path" | |
| else | |
| echo "Error: Failed to compress '$relative_path'. Restoring original file." | |
| # 失敗した場合、一時ファイルを削除してオリジナルファイルを復元 | |
| rm -f "$temp_file" | |
| continue | |
| fi | |
| fi | |
| processed_files=$((processed_files + 1)) | |
| done | |
| echo "----------------------------------------------------" | |
| if [ "$processed_files" -eq 0 ]; then | |
| echo "No PNG files found to process." | |
| else | |
| if [ "$DRY_RUN" -eq 1 ]; then | |
| echo "Dry run complete. Found $processed_files PNG file(s)." | |
| else | |
| echo "Successfully re-compressed $processed_files PNG file(s)." | |
| fi | |
| fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment