メインコンテンツへスキップ

HTML圧縮アーカイブの仕組み理解ツールつくってみた

    カラフルな図解を
    
    ```html
    <!DOCTYPE html>
    <html lang="ja">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>圧縮アーカイブ解説 - ステップバイステップ</title>
        <style>
            body {
                font-family: 'Arial', sans-serif;
                background: linear-gradient(135deg, #667eea  0%, #764ba2  100%);
                margin: 0;
                padding: 20px;
                min-height: 100vh;
            }
            
            .container {
                max-width: 900px;
                margin: 0 auto;
                background: white;
                border-radius: 20px;
                padding: 40px;
                box-shadow: 0 20px 60px rgba(0,0,0,0.3);
            }
            
            h1 {
                text-align: center;
                color: #667eea ;
                margin-bottom: 10px;
            }
            
            .subtitle {
                text-align: center;
                color: #666 ;
                margin-bottom: 40px;
                font-size: 18px;
            }
            
            .step-container {
                margin: 30px 0;
                padding: 30px;
                background: #f8f9ff ;
                border-radius: 15px;
                border: 3px solid #667eea ;
                display: none;
            }
            
            .step-container.active {
                display: block;
                animation: slideIn 0.5s ease;
            }
            
            @keyframes slideIn {
                from {
                    opacity: 0;
                    transform: translateY(20px);
                }
                to {
                    opacity: 1;
                    transform: translateY(0);
                }
            }
            
            .step-title {
                font-size: 24px;
                font-weight: bold;
                color: #667eea ;
                margin-bottom: 20px;
                display: flex;
                align-items: center;
            }
            
            .step-number {
                background: #667eea ;
                color: white;
                width: 40px;
                height: 40px;
                border-radius: 50%;
                display: flex;
                align-items: center;
                justify-content: center;
                margin-right: 15px;
                font-size: 20px;
            }
            
            .visual-box {
                display: flex;
                justify-content: center;
                align-items: center;
                gap: 20px;
                margin: 30px 0;
                flex-wrap: wrap;
            }
            
            .file {
                background: #4CAF50 ;
                color: white;
                padding: 20px 30px;
                border-radius: 10px;
                font-weight: bold;
                box-shadow: 0 4px 10px rgba(0,0,0,0.2);
                animation: pulse 2s infinite;
            }
            
            @keyframes pulse {
                0%, 100% { transform: scale(1); }
                50% { transform: scale(1.05); }
            }
            
            .archive {
                background: #FF9800 ;
                color: white;
                padding: 30px 40px;
                border-radius: 15px;
                font-weight: bold;
                box-shadow: 0 6px 15px rgba(0,0,0,0.3);
                position: relative;
                border: 3px dashed white;
            }
            
            .archive::before {
                content: '📦';
                position: absolute;
                top: -20px;
                right: -20px;
                font-size: 40px;
            }
            
            .compressed {
                background: #2196F3 ;
                color: white;
                padding: 35px 45px;
                border-radius: 20px;
                font-weight: bold;
                box-shadow: 0 8px 20px rgba(0,0,0,0.4);
                position: relative;
            }
            
            .compressed::before {
                content: '🗜️';
                position: absolute;
                top: -25px;
                right: -25px;
                font-size: 50px;
            }
            
            .arrow {
                font-size: 40px;
                color: #667eea ;
                animation: bounce 1s infinite;
            }
            
            @keyframes bounce {
                0%, 100% { transform: translateX(0); }
                50% { transform: translateX(10px); }
            }
            
            .command-box {
                background: #2d3748 ;
                color: #68d391 ;
                padding: 15px 20px;
                border-radius: 10px;
                font-family: 'Courier New', monospace;
                margin: 20px 0;
                font-size: 16px;
                box-shadow: 0 4px 10px rgba(0,0,0,0.3);
            }
            
            .command-box::before {
                content: '$ ';
                color: #90cdf4 ;
            }
            
            .explanation {
                background: #fff5e1 ;
                padding: 20px;
                border-radius: 10px;
                border-left: 5px solid #ffa726 ;
                margin: 20px 0;
                line-height: 1.8;
            }
            
            .button-container {
                display: flex;
                justify-content: center;
                gap: 20px;
                margin-top: 30px;
            }
            
            button {
                background: #667eea ;
                color: white;
                border: none;
                padding: 15px 40px;
                border-radius: 50px;
                font-size: 18px;
                font-weight: bold;
                cursor: pointer;
                transition: all 0.3s;
                box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
            }
            
            button:hover {
                background: #5568d3 ;
                transform: translateY(-2px);
                box-shadow: 0 6px 20px rgba(102, 126, 234, 0.6);
            }
            
            button:disabled {
                background: #ccc ;
                cursor: not-allowed;
                transform: none;
                box-shadow: none;
            }
            
            .progress-bar {
                display: flex;
                justify-content: center;
                gap: 10px;
                margin-bottom: 30px;
            }
            
            .progress-dot {
                width: 15px;
                height: 15px;
                border-radius: 50%;
                background: #ddd ;
                transition: all 0.3s;
            }
            
            .progress-dot.active {
                background: #667eea ;
                transform: scale(1.3);
            }
            
            .highlight {
                background: #ffd700 ;
                padding: 3px 8px;
                border-radius: 5px;
                font-weight: bold;
            }
        </style>
    </head>
    <body>
        <div class="container">
            <h1>🎯 圧縮アーカイブの仕組み</h1>
            <div class="subtitle">gunzip と tar の違いを理解しよう!</div>
            
            <div class="progress-bar" id="progressBar"></div>
            
            <!-- Step 0: はじめに -->
            <div class="step-container active" id="step0">
                <div class="step-title">
                    <div class="step-number">📚</div>
                    はじめに
                </div>
                <div class="explanation">
                    <p><strong>問題:</strong> texts.tgz というファイルに a.txt と b.txt が入っています。</p>
                    <p><strong>質問:</strong> <span class="highlight">gunzip texts.tgz</span> を実行すると、何が残る?</p>
                    <p style="margin-top: 20px;">これから、ステップバイステップで見ていきましょう! 🚀</p>
                </div>
            </div>
            
            <!-- Step 1: 元のファイル -->
            <div class="step-container" id="step1">
                <div class="step-title">
                    <div class="step-number">1</div>
                    元のファイル
                </div>
                <div class="visual-box">
                    <div class="file">📄 a.txt</div>
                    <div class="file">📄 b.txt</div>
                </div>
                <div class="explanation">
                    最初に <strong>2つの別々のファイル</strong> があります。
                </div>
            </div>
            
            <!-- Step 2: tar でアーカイブ化 -->
            <div class="step-container" id="step2">
                <div class="step-title">
                    <div class="step-number">2</div>
                    tar でアーカイブ化
                </div>
                <div class="visual-box">
                    <div class="file">📄 a.txt</div>
                    <div class="file">📄 b.txt</div>
                    <div class="arrow">→</div>
                    <div class="archive">
                        texts.tar<br>
                        <small>(a.txt + b.txt)</small>
                    </div>
                </div>
                <div class="command-box">tar -cf texts.tar a.txt b.txt</div>
                <div class="explanation">
                    <strong>tar</strong> は複数のファイルを <span class="highlight">1つの箱</span> にまとめます。<br>
                    📦 箱の名前: <strong>texts.tar</strong><br>
                    中身はまだ圧縮されていません(元のサイズのまま)。
                </div>
            </div>
            
            <!-- Step 3: gzip で圧縮 -->
            <div class="step-container" id="step3">
                <div class="step-title">
                    <div class="step-number">3</div>
                    gzip で圧縮
                </div>
                <div class="visual-box">
                    <div class="archive">
                        texts.tar<br>
                        <small>(a.txt + b.txt)</small>
                    </div>
                    <div class="arrow">→</div>
                    <div class="compressed">
                        texts.tgz<br>
                        <small>(圧縮済み)</small>
                    </div>
                </div>
                <div class="command-box">gzip texts.tar</div>
                <div class="explanation">
                    <strong>gzip</strong> は箱全体を <span class="highlight">ギュッと圧縮</span> します。<br>
                    🗜️ <strong>texts.tar</strong> → <strong>texts.tgz</strong> (または texts.tar.gz)<br>
                    サイズが小さくなります!
                </div>
            </div>
            
            <!-- Step 4: gunzip で解凍 (問題のポイント!) -->
            <div class="step-container" id="step4">
                <div class="step-title">
                    <div class="step-number">4</div>
                    gunzip で解凍 ⚡ (ここが問題!)
                </div>
                <div class="visual-box">
                    <div class="compressed">
                        texts.tgz<br>
                        <small>(圧縮済み)</small>
                    </div>
                    <div class="arrow">→</div>
                    <div class="archive">
                        texts.tar<br>
                        <small>(a.txt + b.txt)</small>
                    </div>
                </div>
                <div class="command-box">gunzip texts.tgz</div>
                <div class="explanation" style="border-color: #f44336 ; background: #ffebee ;">
                    <strong style="color: #f44336 ;">⚠️ 重要!</strong><br>
                    <strong>gunzip</strong> は <span class="highlight">圧縮を解除するだけ</span> です。<br>
                    箱(tar)は <strong>まだ閉じたまま</strong>!<br>
                    <br>
                    📦 結果: <strong style="color: #f44336 ;">texts.tar のみ</strong> が残る<br>
                    ❌ a.txt と b.txt は <strong>まだ取り出されていない</strong>
                </div>
            </div>
            
            <!-- Step 5: tar で展開 (正解の完全な流れ) -->
            <div class="step-container" id="step5">
                <div class="step-title">
                    <div class="step-number">5</div>
                    tar で展開 (ファイルを取り出す)
                </div>
                <div class="visual-box">
                    <div class="archive">
                        texts.tar<br>
                        <small>(a.txt + b.txt)</small>
                    </div>
                    <div class="arrow">→</div>
                    <div class="file">📄 a.txt</div>
                    <div class="file">📄 b.txt</div>
                </div>
                <div class="command-box">tar -xf texts.tar</div>
                <div class="explanation">
                    箱からファイルを取り出すには、<strong>tar -xf</strong> が必要です。<br>
                    これでやっと a.txt と b.txt が手に入ります! 🎉
                </div>
            </div>
            
            <!-- Step 6: まとめ -->
            <div class="step-container" id="step6">
                <div class="step-title">
                    <div class="step-number">✅</div>
                    まとめ
                </div>
                <div class="explanation" style="background: #e8f5e9 ; border-color: #4CAF50 ;">
                    <h3 style="color: #4CAF50 ; margin-top: 0;">問題の答え: texts.tar のみ</h3>
                    <p><strong>gunzip texts.tgz</strong> を実行すると:</p>
                    <ul>
                        <li>✅ texts.tgz の圧縮が解除される</li>
                        <li>✅ texts.tar ができる</li>
                        <li>❌ a.txt と b.txt は <strong>まだ中に入ったまま</strong></li>
                    </ul>
                </div>
                
                <div class="explanation" style="background: #fff3e0 ; border-color: #FF9800 ; margin-top: 20px;">
                    <h3 style="color: #FF9800 ; margin-top: 0;">💡 よく使うコマンド</h3>
                    <div class="command-box">tar -xzf texts.tgz</div>
                    <p>このコマンドなら、<strong>解凍と展開を一度に</strong> できます!</p>
                    <ul>
                        <li><strong>-x</strong>: 展開(extract)</li>
                        <li><strong>-z</strong>: gzip解凍</li>
                        <li><strong>-f</strong>: ファイル指定</li>
                    </ul>
                </div>
                
                <div class="explanation" style="background: #e3f2fd ; border-color: #2196F3 ; margin-top: 20px;">
                    <h3 style="color: #2196F3 ; margin-top: 0;">🔑 覚え方</h3>
                    <p><strong>gunzip</strong> = 圧縮を「解く」だけ<br>
                    <strong>tar -x</strong> = 箱を「開ける」</p>
                    <p>2段階の作業です! 🎯</p>
                </div>
            </div>
            
            <div class="button-container">
                <button id="prevBtn" onclick="changeStep(-1)">⬅️ 前へ</button>
                <button id="nextBtn" onclick="changeStep(1)">次へ ➡️</button>
            </div>
        </div>
        
        <script>
            let currentStep = 0;
            const totalSteps = 7;
            
            function updateProgress() {
                const progressBar = document.getElementById('progressBar');
                progressBar.innerHTML = '';
                for (let i = 0; i < totalSteps; i++) {
                    const dot = document.createElement('div');
                    dot.className = 'progress-dot' + (i === currentStep ? ' active' : '');
                    progressBar.appendChild(dot);
                }
            }
            
            function changeStep(direction) {
                const steps = document.querySelectorAll('.step-container');
                steps[currentStep].classList.remove('active');
                
                currentStep += direction;
                
                if (currentStep < 0) currentStep = 0;
                if (currentStep >= totalSteps) currentStep = totalSteps - 1;
                
                steps[currentStep].classList.add('active');
                
                document.getElementById('prevBtn').disabled = currentStep === 0;
                document.getElementById('nextBtn').disabled = currentStep === totalSteps - 1;
                
                updateProgress();
            }
            
            // 初期化
            document.getElementById('prevBtn').disabled = true;
            updateProgress();
        </script>
    </body>
    </html>
    ```
    
    ボタンを押して、ステップごとに進めてみてください! 🎯
    
    - 📦 **tar** = ファイルを箱に入れる
    - 🗜️ **gzip** = 箱を圧縮する
    - 🔓 **gunzip** = 圧縮を解除する(でも箱は閉じたまま!)
    
    


    圧縮アーカイブの仕組み

    texts.tgz は実は 2段階 の処理がされています:

    元のファイル → tar でアーカイブ化 → gzip で圧縮
    a.txt, b.txt → texts.tar → texts.tgz
    

    gunzip の動作

    gunzip texts.tgz を実行すると:

    # 実行前
    texts.tgz (gzip圧縮されたtarアーカイブ)
    
    # gunzip texts.tgz を実行
    ↓
    
    # 実行後
    texts.tar (tarアーカイブ、まだa.txtとb.txtは入ったまま)
    

    重要なポイント:

    • gunzip は gzip圧縮の解除のみ を行う

    • 元の texts.tgz は削除される

    • tarアーカイブの中身(a.txt, b.txt)は まだ取り出されていない

    個々のファイルを取り出すには

    # 方法1: 2段階で実行
    gunzip texts.tgz    # → texts.tar ができる
    tar -xf texts.tar   # → a.txt, b.txt が取り出される
    
    # 方法2: 一度に実行(こちらが一般的)
    tar -xzf texts.tgz  # -z オプションでgzip解凍も同時実行
    # または
    tar -xf texts.tgz   # 最近のtarは自動認識する
    

    図解

    texts.tgz
        ↓ gunzip texts.tgz
    texts.tar (箱の中にa.txtとb.txtが入っている状態)
        ↓ tar -xf texts.tar
    a.txt
    b.txt
    

    つまり: gunzip だけでは「圧縮を解除して箱(tar)を開ける」だけで、「箱の中身を取り出す」ところまではやらない、ということです。


    あなたへのおすすめ