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)を開ける」だけで、「箱の中身を取り出す」ところまではやらない、ということです。