terminal-quest 1.1.2 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/App.js +2 -2
- package/dist/components/HintBar.js +3 -2
- package/dist/data/commands-meta.js +112 -106
- package/dist/data/stories/00-beginner-pc.js +127 -112
- package/dist/data/stories/01-first-server.js +11 -5
- package/dist/data/stories/02-messy-project.js +14 -7
- package/dist/data/stories/03-log-detective.js +22 -6
- package/dist/data/stories/04-deploy-day.js +64 -10
- package/dist/data/stories/05-git-incident.js +80 -19
- package/dist/data/stories/06-pipe-master.js +74 -14
- package/dist/data/stories/07-dangerous-commands.js +79 -12
- package/dist/data/stories/k1-treasure-hunt.js +160 -145
- package/dist/data/types.d.ts +1 -1
- package/dist/engine/CommandFeedback.js +10 -3
- package/dist/engine/CommandHandler.js +5 -0
- package/dist/engine/commands/cat.js +12 -1
- package/dist/engine/commands/cut.js +3 -0
- package/dist/engine/commands/grep.js +6 -0
- package/dist/engine/commands/head.js +3 -0
- package/dist/engine/commands/help.js +7 -3
- package/dist/engine/commands/sort.js +3 -0
- package/dist/engine/commands/tail.js +3 -0
- package/dist/engine/commands/uniq.js +3 -0
- package/dist/screens/StorySelectScreen.d.ts +2 -1
- package/dist/screens/StorySelectScreen.js +55 -7
- package/dist/screens/TerminalScreen.js +67 -17
- package/dist/state/useGameState.d.ts +1 -0
- package/dist/state/useGameState.js +13 -2
- package/package.json +1 -1
|
@@ -67,7 +67,7 @@ const salesCsvLines = [
|
|
|
67
67
|
'営業,175000',
|
|
68
68
|
'人事,135000',
|
|
69
69
|
'開発,240000',
|
|
70
|
-
].join('\n');
|
|
70
|
+
].join('\n') + '\n';
|
|
71
71
|
const mission2FS = {
|
|
72
72
|
type: 'directory',
|
|
73
73
|
children: {
|
|
@@ -231,12 +231,15 @@ export const story06 = {
|
|
|
231
231
|
objectives: [
|
|
232
232
|
{
|
|
233
233
|
id: 'obj-06-01-01',
|
|
234
|
-
description: '
|
|
235
|
-
checks: [
|
|
234
|
+
description: 'ログの先頭5行だけを表示する',
|
|
235
|
+
checks: [
|
|
236
|
+
{ type: 'command_executed', command: 'head' },
|
|
237
|
+
{ type: 'output_contains', pattern: '08:00:01' },
|
|
238
|
+
],
|
|
236
239
|
hints: [
|
|
237
240
|
{ level: 1, text: 'コマンドの出力を別のコマンドに渡す記号があります。' },
|
|
238
|
-
{ level: 2, text: '
|
|
239
|
-
{ level: 3, text: '「
|
|
241
|
+
{ level: 2, text: 'cat でログを表示し、パイプ(|)で head に渡します。head -n 5 で先頭5行だけ取得できます。' },
|
|
242
|
+
{ level: 3, text: '「cat logs/access.log | head -n 5」と入力してEnterを押してください。' },
|
|
240
243
|
],
|
|
241
244
|
},
|
|
242
245
|
{
|
|
@@ -251,8 +254,22 @@ export const story06 = {
|
|
|
251
254
|
{ level: 2, text: 'cat と grep をパイプで繋ぎます。直接 grep にファイルを指定してもOKです。' },
|
|
252
255
|
{ level: 3, text: '「cat logs/access.log | grep ERROR」と入力してEnterを押してください。' },
|
|
253
256
|
],
|
|
257
|
+
feedbacks: [
|
|
258
|
+
{ pattern: 'grep error', message: '大文字と小文字は区別されます。ERROR を検索するには大文字で「grep ERROR」と入力しましょう。' },
|
|
259
|
+
],
|
|
254
260
|
},
|
|
255
261
|
],
|
|
262
|
+
review: {
|
|
263
|
+
question: 'パイプ(|)の役割は何ですか?',
|
|
264
|
+
choices: [
|
|
265
|
+
'ファイルを削除する',
|
|
266
|
+
'左のコマンドの出力を右のコマンドの入力に渡す',
|
|
267
|
+
'ファイルに保存する',
|
|
268
|
+
'コマンドを同時に実行する',
|
|
269
|
+
],
|
|
270
|
+
correctIndex: 1,
|
|
271
|
+
explanation: 'パイプ(|)は左のコマンドの出力を、右のコマンドの入力として渡します。これにより複数のコマンドをつなげて、複雑なデータ処理ができます。',
|
|
272
|
+
},
|
|
256
273
|
},
|
|
257
274
|
{
|
|
258
275
|
id: 'mission-06-02',
|
|
@@ -265,21 +282,28 @@ export const story06 = {
|
|
|
265
282
|
objectives: [
|
|
266
283
|
{
|
|
267
284
|
id: 'obj-06-02-01',
|
|
268
|
-
description: '
|
|
285
|
+
description: 'cut と sort | uniq でユニークな部門名をすべて表示する',
|
|
269
286
|
checks: [
|
|
270
|
-
{ type: 'command_executed', command: '
|
|
287
|
+
{ type: 'command_executed', command: 'cut' },
|
|
271
288
|
{ type: 'output_contains', pattern: '\u55B6\u696D' },
|
|
272
289
|
],
|
|
273
290
|
hints: [
|
|
274
291
|
{ level: 1, text: 'CSVの特定の列を抽出して、重複を除去しましょう。' },
|
|
275
|
-
{ level: 2, text: 'cut
|
|
292
|
+
{ level: 2, text: 'cut コマンドで列を指定します。-d, は「カンマ区切り」、-f1 は「1列目」の意味です。その結果を sort | uniq に渡しましょう。' },
|
|
276
293
|
{ level: 3, text: '「cut -d, -f1 sales.csv | sort | uniq」と入力してEnterを押してください。' },
|
|
277
294
|
],
|
|
295
|
+
feedbacks: [
|
|
296
|
+
{ pattern: 'cut -f1', message: '-d オプションで区切り文字を指定し忘れていませんか?CSVなので -d, が必要です。' },
|
|
297
|
+
{ pattern: 'sort.*uniq.*sales', message: 'まず cut で部門列を抽出してから、sort | uniq に渡しましょう。' },
|
|
298
|
+
],
|
|
278
299
|
},
|
|
279
300
|
{
|
|
280
301
|
id: 'obj-06-02-02',
|
|
281
|
-
description: '
|
|
282
|
-
checks: [
|
|
302
|
+
description: 'wc -l で sales.csv の行数を数える',
|
|
303
|
+
checks: [
|
|
304
|
+
{ type: 'command_executed', command: 'wc' },
|
|
305
|
+
{ type: 'output_contains', pattern: '20' },
|
|
306
|
+
],
|
|
283
307
|
hints: [
|
|
284
308
|
{ level: 1, text: '行数を数えるコマンドを使いましょう。' },
|
|
285
309
|
{ level: 2, text: 'wc -l コマンドでファイルの行数を数えられます。' },
|
|
@@ -287,6 +311,17 @@ export const story06 = {
|
|
|
287
311
|
],
|
|
288
312
|
},
|
|
289
313
|
],
|
|
314
|
+
review: {
|
|
315
|
+
question: 'sort | uniq の順番が重要な理由は何ですか?',
|
|
316
|
+
choices: [
|
|
317
|
+
'uniq の方が処理が遅いから',
|
|
318
|
+
'uniq は隣り合う重複行しか除去しないので、先に sort で並べる必要がある',
|
|
319
|
+
'sort が uniq の結果を上書きするから',
|
|
320
|
+
'特に理由はない。逆順でも同じ結果になる',
|
|
321
|
+
],
|
|
322
|
+
correctIndex: 1,
|
|
323
|
+
explanation: 'uniq は「隣り合った行」が同じ場合だけ重複を除去します。そのため、先に sort でデータを並べ替えて同じ値を隣り合わせにしてから、uniq で重複除去するのが正しい手順です。',
|
|
324
|
+
},
|
|
290
325
|
},
|
|
291
326
|
{
|
|
292
327
|
id: 'mission-06-03',
|
|
@@ -313,15 +348,29 @@ export const story06 = {
|
|
|
313
348
|
},
|
|
314
349
|
{
|
|
315
350
|
id: 'obj-06-03-02',
|
|
316
|
-
description: '
|
|
351
|
+
description: 'sort -t, -k3 -n で年齢(3列目)の数値順にソートする',
|
|
317
352
|
checks: [{ type: 'command_executed', command: 'sort' }],
|
|
318
353
|
hints: [
|
|
319
354
|
{ level: 1, text: '数値でソートするオプションがあります。' },
|
|
320
|
-
{ level: 2, text: 'sort
|
|
355
|
+
{ level: 2, text: 'sort -t, は「カンマ区切り」、-k3 は「3番目の列でソート」、-n は「数値として並べる」の意味です。年齢は3列目にあります。' },
|
|
321
356
|
{ level: 3, text: '「sort -t, -k3 -n employees.csv」と入力してEnterを押してください。' },
|
|
322
357
|
],
|
|
358
|
+
feedbacks: [
|
|
359
|
+
{ pattern: '^sort employees', message: 'オプションなしの sort は1列目で文字順にソートします。年齢(3列目)で数値ソートするには -t, -k3 -n が必要です。' },
|
|
360
|
+
],
|
|
323
361
|
},
|
|
324
362
|
],
|
|
363
|
+
review: {
|
|
364
|
+
question: 'cut -d, -f2 の -d と -f はそれぞれ何を指定しますか?',
|
|
365
|
+
choices: [
|
|
366
|
+
'-d はディレクトリ、-f はファイル',
|
|
367
|
+
'-d は区切り文字(delimiter)、-f はフィールド番号',
|
|
368
|
+
'-d は削除、-f はフィルター',
|
|
369
|
+
'-d はデータ型、-f はフォーマット',
|
|
370
|
+
],
|
|
371
|
+
correctIndex: 1,
|
|
372
|
+
explanation: '-d は区切り文字(delimiter)を指定します。-d, ならカンマ区切りです。-f はフィールド番号で、-f2 なら2番目の列を取り出します。CSVデータの加工に欠かせないコマンドです。',
|
|
373
|
+
},
|
|
325
374
|
},
|
|
326
375
|
{
|
|
327
376
|
id: 'mission-06-04',
|
|
@@ -347,7 +396,7 @@ export const story06 = {
|
|
|
347
396
|
},
|
|
348
397
|
{
|
|
349
398
|
id: 'obj-06-04-02',
|
|
350
|
-
description: '
|
|
399
|
+
description: 'ERROR行からサービス名を抽出し、サービス別エラー件数を集計する(4段パイプ)',
|
|
351
400
|
checks: [
|
|
352
401
|
{ type: 'command_executed', command: 'uniq' },
|
|
353
402
|
{ type: 'output_contains', pattern: 'web' },
|
|
@@ -368,11 +417,22 @@ export const story06 = {
|
|
|
368
417
|
],
|
|
369
418
|
hints: [
|
|
370
419
|
{ level: 1, text: '前の集計結果をさらにソートして上位だけ取り出しましょう。' },
|
|
371
|
-
{ level: 2, text: '
|
|
420
|
+
{ level: 2, text: '件数の多い順に並べるには sort -rn(数値の逆順ソート)を使います。上位だけ取るには head を使いましょう。' },
|
|
372
421
|
{ level: 3, text: '「grep ERROR report.log | cut -d" " -f2 | sort | uniq -c | sort -rn | head -n 3」と入力してEnterを押してください。' },
|
|
373
422
|
],
|
|
374
423
|
},
|
|
375
424
|
],
|
|
425
|
+
review: {
|
|
426
|
+
question: '「grep ERROR report.log | cut -d" " -f2 | sort | uniq -c」のパイプの流れとして正しいのはどれ?',
|
|
427
|
+
choices: [
|
|
428
|
+
'ファイル作成 → 検索 → 並べ替え → カウント',
|
|
429
|
+
'ERROR行を抽出 → サービス名を取り出し → 並べ替え → 重複をカウント',
|
|
430
|
+
'並べ替え → 抽出 → カウント → 表示',
|
|
431
|
+
'カウント → 並べ替え → 抽出 → 表示',
|
|
432
|
+
],
|
|
433
|
+
correctIndex: 1,
|
|
434
|
+
explanation: 'パイプは左から右へ順番に処理されます。まず grep でERROR行だけを抽出し、cut でサービス名の列を取り出し、sort で並べ替えてから、uniq -c で重複をカウントします。',
|
|
435
|
+
},
|
|
376
436
|
},
|
|
377
437
|
],
|
|
378
438
|
unlockRequires: ['story-03'],
|
|
@@ -258,14 +258,14 @@ export const story07 = {
|
|
|
258
258
|
},
|
|
259
259
|
{
|
|
260
260
|
id: 'obj-07-01-02',
|
|
261
|
-
description: 'cat
|
|
261
|
+
description: 'cat data/important.csv で重要データの内容を確認する',
|
|
262
262
|
checks: [
|
|
263
263
|
{ type: 'command_executed', command: 'cat' },
|
|
264
|
-
{ type: 'output_contains', pattern: '
|
|
264
|
+
{ type: 'output_contains', pattern: 'Tanaka' },
|
|
265
265
|
],
|
|
266
266
|
hints: [
|
|
267
267
|
{ level: 1, text: '\u30D5\u30A1\u30A4\u30EB\u306E\u4E2D\u8EAB\u3092\u8868\u793A\u3059\u308B\u30B3\u30DE\u30F3\u30C9\u3067\u3001\u91CD\u8981\u306A\u30C7\u30FC\u30BF\u3092\u78BA\u8A8D\u3057\u307E\u3057\u3087\u3046\u3002' },
|
|
268
|
-
{ level: 2, text: 'cat
|
|
268
|
+
{ level: 2, text: 'cat コマンドで data/important.csv を見てみましょう。重要なデータが含まれています。' },
|
|
269
269
|
{ level: 3, text: '\u300Ccat data/important.csv\u300D\u3068\u5165\u529B\u3057\u3066Enter\u3092\u62BC\u3057\u3066\u304F\u3060\u3055\u3044\u3002' },
|
|
270
270
|
],
|
|
271
271
|
},
|
|
@@ -278,8 +278,23 @@ export const story07 = {
|
|
|
278
278
|
{ level: 2, text: 'rm \u30B3\u30DE\u30F3\u30C9\u3067\u30D5\u30A1\u30A4\u30EB\u3092\u524A\u9664\u3067\u304D\u307E\u3059\u3002\u524A\u9664\u5BFE\u8C61\u3092\u9593\u9055\u3048\u306A\u3044\u3088\u3046\u306B\uFF01' },
|
|
279
279
|
{ level: 3, text: '\u300Crm data/backup.csv\u300D\u3068\u5165\u529B\u3057\u3066Enter\u3092\u62BC\u3057\u3066\u304F\u3060\u3055\u3044\u3002' },
|
|
280
280
|
],
|
|
281
|
+
feedbacks: [
|
|
282
|
+
{ pattern: 'rm data/important', message: 'important.csv は重要なデータです!削除するのは backup.csv の方です。' },
|
|
283
|
+
{ pattern: '^rm backup', message: 'backup.csv は data/ フォルダの中にあります。パスを指定して rm data/backup.csv としましょう。' },
|
|
284
|
+
],
|
|
281
285
|
},
|
|
282
286
|
],
|
|
287
|
+
review: {
|
|
288
|
+
question: 'ファイルを削除する前にまずやるべきことは何ですか?',
|
|
289
|
+
choices: [
|
|
290
|
+
'すぐに rm で削除する',
|
|
291
|
+
'ls と cat で中身を確認して、削除対象を間違えないようにする',
|
|
292
|
+
'ディレクトリごと rm -rf で削除する',
|
|
293
|
+
'別のサーバーにコピーする',
|
|
294
|
+
],
|
|
295
|
+
correctIndex: 1,
|
|
296
|
+
explanation: '削除する前に ls でファイル一覧を確認し、cat で中身を見て「本当に消して大丈夫か」を確認する習慣が大切です。一度削除したファイルは元に戻せません。',
|
|
297
|
+
},
|
|
283
298
|
},
|
|
284
299
|
{
|
|
285
300
|
id: 'mission-07-02',
|
|
@@ -305,7 +320,7 @@ export const story07 = {
|
|
|
305
320
|
},
|
|
306
321
|
{
|
|
307
322
|
id: 'obj-07-02-02',
|
|
308
|
-
description: '
|
|
323
|
+
description: 'cp で server.conf を backups/ にバックアップする',
|
|
309
324
|
checks: [{ type: 'file_exists', path: '/home/project/backups/server.conf' }],
|
|
310
325
|
hints: [
|
|
311
326
|
{ level: 1, text: '\u30D5\u30A1\u30A4\u30EB\u3092\u30B3\u30D4\u30FC\u3059\u308B\u30B3\u30DE\u30F3\u30C9\u3092\u4F7F\u3044\u307E\u3057\u3087\u3046\u3002' },
|
|
@@ -315,15 +330,26 @@ export const story07 = {
|
|
|
315
330
|
},
|
|
316
331
|
{
|
|
317
332
|
id: 'obj-07-02-03',
|
|
318
|
-
description: '
|
|
333
|
+
description: '不要な app.log を rm で安全に削除する',
|
|
319
334
|
checks: [{ type: 'file_not_exists', path: '/home/project/app.log' }],
|
|
320
335
|
hints: [
|
|
321
|
-
{ level: 1, text: '
|
|
336
|
+
{ level: 1, text: 'バックアップが取れたので、不要なログファイルを安全に削除しましょう。' },
|
|
322
337
|
{ level: 2, text: 'rm \u30B3\u30DE\u30F3\u30C9\u3067\u30D5\u30A1\u30A4\u30EB\u3092\u524A\u9664\u3067\u304D\u307E\u3059\u3002\u30ED\u30B0\u30D5\u30A1\u30A4\u30EB\u306F\u4E0D\u8981\u3067\u3059\u306D\u3002' },
|
|
323
338
|
{ level: 3, text: '\u300Crm app.log\u300D\u3068\u5165\u529B\u3057\u3066Enter\u3092\u62BC\u3057\u3066\u304F\u3060\u3055\u3044\u3002' },
|
|
324
339
|
],
|
|
325
340
|
},
|
|
326
341
|
],
|
|
342
|
+
review: {
|
|
343
|
+
question: 'ファイル削除の安全な手順として正しいのはどれ?',
|
|
344
|
+
choices: [
|
|
345
|
+
'rm で削除 → 必要だったら復元する',
|
|
346
|
+
'ls で確認 → バックアップを作成(cp) → 不要ファイルを削除(rm)',
|
|
347
|
+
'バックアップなしで即削除する',
|
|
348
|
+
'ファイル名を変更してから削除する',
|
|
349
|
+
],
|
|
350
|
+
correctIndex: 1,
|
|
351
|
+
explanation: '安全な手順は「確認 → バックアップ → 削除」です。ls で内容を確認し、cp で重要なファイルをバックアップしてから、不要なファイルだけを rm で削除しましょう。',
|
|
352
|
+
},
|
|
327
353
|
},
|
|
328
354
|
{
|
|
329
355
|
id: 'mission-07-03',
|
|
@@ -346,18 +372,26 @@ export const story07 = {
|
|
|
346
372
|
},
|
|
347
373
|
{
|
|
348
374
|
id: 'obj-07-03-02',
|
|
349
|
-
description: '
|
|
375
|
+
description: 'rm -rf で old-build だけを削除する(src と dist は残す)',
|
|
350
376
|
checks: [{ type: 'file_not_exists', path: '/home/project/old-build' }],
|
|
351
377
|
hints: [
|
|
352
378
|
{ level: 1, text: '\u53E4\u3044\u30D3\u30EB\u30C9\u7D50\u679C\u3060\u3051\u3092\u524A\u9664\u3057\u307E\u3057\u3087\u3046\u3002\u30BD\u30FC\u30B9\u30B3\u30FC\u30C9\u3092\u524A\u9664\u3057\u306A\u3044\u3088\u3046\u6CE8\u610F\uFF01' },
|
|
353
379
|
{ level: 2, text: 'rm -rf \u3067\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3054\u3068\u524A\u9664\u3067\u304D\u307E\u3059\u3002old-build \u3092\u524A\u9664\u3057\u307E\u3057\u3087\u3046\u3002' },
|
|
354
380
|
{ level: 3, text: '\u300Crm -rf old-build\u300D\u3068\u5165\u529B\u3057\u3066Enter\u3092\u62BC\u3057\u3066\u304F\u3060\u3055\u3044\u3002' },
|
|
355
381
|
],
|
|
382
|
+
feedbacks: [
|
|
383
|
+
{ pattern: 'rm -rf src', message: 'src はソースコードが入った大切なディレクトリです!削除するのは old-build の方です。' },
|
|
384
|
+
{ pattern: 'rm -rf dist', message: 'dist は現在のビルド結果です。削除するのは old-build の方です。' },
|
|
385
|
+
{ pattern: '^rm old-build$', message: 'ディレクトリを中身ごと削除するには -rf オプションが必要です。rm -rf old-build としましょう。' },
|
|
386
|
+
],
|
|
356
387
|
},
|
|
357
388
|
{
|
|
358
389
|
id: 'obj-07-03-03',
|
|
359
390
|
description: 'src \u304C\u6B8B\u3063\u3066\u3044\u308B\u3053\u3068\u3092\u78BA\u8A8D\u3059\u308B',
|
|
360
|
-
checks: [
|
|
391
|
+
checks: [
|
|
392
|
+
{ type: 'command_executed', command: 'ls' },
|
|
393
|
+
{ type: 'output_contains', pattern: 'main.ts' },
|
|
394
|
+
],
|
|
361
395
|
hints: [
|
|
362
396
|
{ level: 1, text: '\u30BD\u30FC\u30B9\u30B3\u30FC\u30C9\u304C\u7121\u4E8B\u306B\u6B8B\u3063\u3066\u3044\u308B\u304B\u78BA\u8A8D\u3057\u307E\u3057\u3087\u3046\u3002' },
|
|
363
397
|
{ level: 2, text: 'ls \u30B3\u30DE\u30F3\u30C9\u3067 src \u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306E\u4E2D\u8EAB\u3092\u78BA\u8A8D\u3057\u307E\u3057\u3087\u3046\u3002' },
|
|
@@ -365,6 +399,17 @@ export const story07 = {
|
|
|
365
399
|
],
|
|
366
400
|
},
|
|
367
401
|
],
|
|
402
|
+
review: {
|
|
403
|
+
question: 'rm -rf を実行する前に最も重要なことは何ですか?',
|
|
404
|
+
choices: [
|
|
405
|
+
'何も考えずに即実行する',
|
|
406
|
+
'ls で削除対象の中身を確認し、正しいディレクトリだけを指定する',
|
|
407
|
+
'-rf ではなく -r だけを使う',
|
|
408
|
+
'ファイルを先に全部移動する',
|
|
409
|
+
],
|
|
410
|
+
correctIndex: 1,
|
|
411
|
+
explanation: 'rm -rf は確認なしでディレクトリを丸ごと削除する強力なコマンドです。必ず ls で中身を確認し、ソースコードなど重要なファイルを間違えて消さないよう、削除対象を正確に指定しましょう。',
|
|
412
|
+
},
|
|
368
413
|
},
|
|
369
414
|
{
|
|
370
415
|
id: 'mission-07-04',
|
|
@@ -390,18 +435,29 @@ export const story07 = {
|
|
|
390
435
|
},
|
|
391
436
|
{
|
|
392
437
|
id: 'obj-07-04-02',
|
|
393
|
-
description: '
|
|
394
|
-
checks: [
|
|
438
|
+
description: 'find で見つけた app-2024-*.log を rm で削除する',
|
|
439
|
+
checks: [
|
|
440
|
+
{ type: 'file_not_exists', path: '/home/project/logs/app-2024-01.log' },
|
|
441
|
+
{ type: 'file_not_exists', path: '/home/project/logs/app-2024-02.log' },
|
|
442
|
+
{ type: 'file_not_exists', path: '/home/project/logs/app-2024-03.log' },
|
|
443
|
+
],
|
|
395
444
|
hints: [
|
|
396
445
|
{ level: 1, text: 'find \u3067\u898B\u3064\u3051\u305F\u30D5\u30A1\u30A4\u30EB\u3092\u524A\u9664\u3057\u307E\u3057\u3087\u3046\u3002' },
|
|
397
|
-
{ level: 2, text: 'rm
|
|
446
|
+
{ level: 2, text: '前の find で表示されたファイル名を rm コマンドに指定して削除しましょう。' },
|
|
398
447
|
{ level: 3, text: '\u300Crm app-2024-01.log app-2024-02.log app-2024-03.log\u300D\u3068\u5165\u529B\u3057\u3066Enter\u3092\u62BC\u3057\u3066\u304F\u3060\u3055\u3044\u3002' },
|
|
399
448
|
],
|
|
449
|
+
feedbacks: [
|
|
450
|
+
{ pattern: 'rm error.log', message: 'error.log は残すべきファイルです!削除するのは app-2024-*.log だけです。' },
|
|
451
|
+
{ pattern: 'rm access.log', message: 'access.log は残すべきファイルです!削除するのは app-2024-*.log だけです。' },
|
|
452
|
+
],
|
|
400
453
|
},
|
|
401
454
|
{
|
|
402
455
|
id: 'obj-07-04-03',
|
|
403
456
|
description: 'error.log \u3092\u6B8B\u3057\u3066\u3044\u308B\u3053\u3068\u3092\u78BA\u8A8D\u3059\u308B',
|
|
404
|
-
checks: [
|
|
457
|
+
checks: [
|
|
458
|
+
{ type: 'command_executed', command: 'ls' },
|
|
459
|
+
{ type: 'output_contains', pattern: 'error.log' },
|
|
460
|
+
],
|
|
405
461
|
hints: [
|
|
406
462
|
{ level: 1, text: '\u6B8B\u3059\u3079\u304D\u30D5\u30A1\u30A4\u30EB\u304C\u7121\u4E8B\u306B\u6B8B\u3063\u3066\u3044\u308B\u304B\u78BA\u8A8D\u3057\u307E\u3057\u3087\u3046\u3002' },
|
|
407
463
|
{ level: 2, text: 'ls \u30B3\u30DE\u30F3\u30C9\u3067\u73FE\u5728\u306E\u30D5\u30A1\u30A4\u30EB\u4E00\u89A7\u3092\u8868\u793A\u3057\u307E\u3057\u3087\u3046\u3002' },
|
|
@@ -409,6 +465,17 @@ export const story07 = {
|
|
|
409
465
|
],
|
|
410
466
|
},
|
|
411
467
|
],
|
|
468
|
+
review: {
|
|
469
|
+
question: '大量のファイルを安全に削除するワークフローとして正しいのは?',
|
|
470
|
+
choices: [
|
|
471
|
+
'rm * で全部削除してから必要なものを復元する',
|
|
472
|
+
'find で削除対象を一覧表示して確認 → rm で対象だけを削除',
|
|
473
|
+
'手当たり次第に削除する',
|
|
474
|
+
'ディレクトリごと rm -rf で削除する',
|
|
475
|
+
],
|
|
476
|
+
correctIndex: 1,
|
|
477
|
+
explanation: 'まず find で削除対象を検索・確認してから、rm で対象ファイルだけを削除するのが安全なワークフローです。「確認してから実行」が鉄則です。',
|
|
478
|
+
},
|
|
412
479
|
},
|
|
413
480
|
],
|
|
414
481
|
};
|