Feature/multilingual quests (#209)

This commit is contained in:
Justin Lin authored and GitHub committed 2026-10-09 22:58:05 +11:00
commit 4260e742df
154 files changed
+2712 -108

No files matched your search

+11 -4
View File
@@ -6,7 +6,7 @@ import { ref, defineProps, onMounted } from 'vue'
import MarkdownText from './MarkdownText.vue'
import { trpc } from '../utils/trpc'
const { t } = useI18n()
const { t, locale } = useI18n()
const props = defineProps({
questTitle: {
@@ -52,8 +52,15 @@ const handleColour = () => {
}
}
onMounted(async () => {
const quest = await trpc.quests.getQuestDetail.query(questId)
questInstruction.value = quest.instruction
try {
const quest = await trpc.quests.getQuestDetail.query({
questId,
locale: locale.value,
})
questInstruction.value = quest.instruction
} catch (error) {
toast.error('Failed to load quest detail:', error)
}
handleColour()
})
</script>
@@ -83,7 +90,7 @@ onMounted(async () => {
target="_blank"
@click="handleQuests(questId)"
:style="{ backgroundColor: questColor, color: questTextColor }"
class="inline-flex justify-center rounded-lg text-base font-black py-3 mt-5 w-full text-lg"
class="inline-flex justify-center rounded-lg text-base font-black py-3 mt-5 w-full"
>
{{ t('quest.start') }}
</a>
+7 -2
View File
@@ -7,7 +7,7 @@ import { trpc } from '../utils/trpc'
import useUserProfile from '../store/userProfile'
import QuestIntro from './QuestIntro.vue'
const { t } = useI18n()
const { t, locale } = useI18n()
const store = useUserProfile()
const toast = useToast()
@@ -66,7 +66,8 @@ async function computeGraphData() {
if (!store.progress) return
try {
const quests = await trpc.quests.getQuests.query()
const quests = await trpc.quests.getQuests.query({ locale: locale.value })
const dag = new DAG(quests)
const nodesValues = dag.getNodes()
@@ -117,6 +118,10 @@ onMounted(async () => {
})
watch(() => store.progress, computeGraphData, { deep: true })
watch(locale, () => {
opened.value = null
computeGraphData()
})
const curvedPath = computed(() => {
return (source: Node, target: Node) => {
+31 -2
View File
@@ -4,15 +4,44 @@ import { useRouter } from 'vue-router'
import { useToast } from 'vue-toastification'
import { useSession } from '../../store/session'
import { openBugReport, openQuestSurvey } from '../../utils/formbricks'
import { trpc } from '../../utils/trpc'
import type { QuestLocale } from '../../../../packages/constants'
const { t } = useI18n()
const { t, locale } = useI18n()
const toast = useToast()
const router = useRouter()
const sessionStore = useSession()
const reset = async () => {
console.log('resetting...')
await sessionStore.createSession()
const selectedLocale = locale.value as QuestLocale
const questId = sessionStore.session?.quest
if (!questId) return
try {
const quests = await trpc.quests.getQuests.query({
locale: selectedLocale,
})
console.log({
selectedLocale,
questId,
availableQuestIds: quests.map((quest) => quest.id),
})
if (!quests.some((quest) => quest.id === questId)) {
toast.warning(t('game.language_unavailable'))
return
}
await sessionStore.createSession()
} catch (error) {
console.error('Failed to reset quest:', error)
toast.error(t('game.reset_failed'))
}
}
const continuePlay = async () => {
try {
router.push({ name: 'map' })
+12 -5
View File
@@ -1,12 +1,17 @@
<script setup lang="ts">
import { useI18n } from 'vue-i18n'
import { setLocale, type SupportedLocale } from '../../i18n'
import { setLocale } from '../../i18n'
import type { QuestLocale } from '../../../../packages/constants'
import {
SUPPORTED_LOCALES,
LOCALE_NAME_MAP,
} from '../../../../packages/constants'
const { locale } = useI18n({ useScope: 'global' })
const { t, locale } = useI18n({ useScope: 'global' })
function changeLanguage(event: Event) {
const selectedLocale = (event.target as HTMLSelectElement)
.value as SupportedLocale
.value as QuestLocale
setLocale(selectedLocale)
}
@@ -15,12 +20,14 @@ function changeLanguage(event: Event) {
<template>
<select
:value="locale"
:title="t('language.change')"
class="bg-bg-secondary px-3 py-2 text-sm text-text shadow-md outline-none"
aria-label="Language"
@change="changeLanguage"
style="font-size: 2vh"
>
<option value="en">English</option>
<option value="zh-TW">繁體中文</option>
<option v-for="locale in SUPPORTED_LOCALES" :key="locale" :value="locale">
{{ LOCALE_NAME_MAP[locale] }}
</option>
</select>
</template>
+6 -8
View File
@@ -1,16 +1,14 @@
import { createI18n } from 'vue-i18n'
import type { QuestLocale } from '../../../packages/constants'
import { SUPPORTED_LOCALES } from '../../../packages/constants'
import en from './locales/en.json'
import zhTW from './locales/zh-TW.json'
export const supportedLocales = ['zh-TW', 'en'] as const
export type SupportedLocale = (typeof supportedLocales)[number]
function isSupportedLocale(locale: string): locale is SupportedLocale {
return supportedLocales.includes(locale as SupportedLocale)
function isSupportedLocale(locale: string): locale is QuestLocale {
return SUPPORTED_LOCALES.includes(locale as QuestLocale)
}
function getInitialLocale(): SupportedLocale {
function getInitialLocale(): QuestLocale {
const savedLocale = localStorage.getItem('locale')
if (savedLocale && isSupportedLocale(savedLocale)) {
@@ -34,7 +32,7 @@ export const i18n = createI18n({
},
})
export function setLocale(locale: SupportedLocale) {
export function setLocale(locale: QuestLocale) {
i18n.global.locale.value = locale
localStorage.setItem('locale', locale)
document.documentElement.lang = locale
+5 -4
View File
@@ -1,8 +1,6 @@
{
"language": {
"change": "Change language",
"traditional_chinese": "繁體中文",
"english": "English"
"change": "Change language"
},
"landing_nav": {
"intro": "Introduction",
@@ -102,6 +100,9 @@
"reset": "Reset",
"continue": "Continue",
"command_book": "Command Book",
"cheatsheets": "Cheat Sheets"
"cheatsheets": "Cheat Sheets",
"reset_to_apply_language": "Reset quest to apply language changes",
"reset_failed": "Reset failed",
"language_unavailable": "This quest does not support the selected language, please choose another language"
}
}
+5 -4
View File
@@ -1,8 +1,6 @@
{
"language": {
"change": "切換語言",
"traditional_chinese": "繁體中文",
"english": "English"
"change": "切換語言"
},
"landing_nav": {
"intro": "前言",
@@ -102,6 +100,9 @@
"reset": "重置",
"continue": "繼續",
"command_book": "指令之書",
"cheatsheets": "指令列表"
"cheatsheets": "指令列表",
"reset_to_apply_language": "重置關卡以套用語言變更",
"reset_failed": "重置失敗",
"language_unavailable": "此關卡不支援所選語言,請選擇其他語言"
}
}
+14 -7
View File
@@ -1,4 +1,5 @@
import { defineStore } from 'pinia'
import type { QuestLocale } from '../../../packages/constants'
import {
FileGraph,
type FileGraphUpdateEvent,
@@ -9,6 +10,7 @@ import Socket from '../utils/socket'
import SocketTerminal from '../utils/terminal'
import type { Session } from '../types'
import { trpc } from '../utils/trpc'
import { i18n } from '../i18n'
const socket = new Socket()
const term = new SocketTerminal()
@@ -41,11 +43,16 @@ export const useSession = defineStore('session', {
quest: null,
}),
actions: {
async setQuest(questId: string) {
this.quest = await trpc.quests.getQuestDetail.query(questId)
async setQuest(questId: string, locale: QuestLocale) {
this.quest = await trpc.quests.getQuestDetail.query({
questId,
locale,
})
this.questId = questId
},
async setSession(session: SessionDetail) {
await this.setQuest(session.quest, session.locale)
this.session = {
...session,
graph: new FileGraph(session.graph),
@@ -60,18 +67,18 @@ export const useSession = defineStore('session', {
term.focus()
},
async createSession() {
const locale = i18n.global.locale.value
const session = await trpc.session.createSession.mutate({
questId: this.questId,
locale,
})
await this.setSession(session)
term.send('echo start\n')
},
async getActiveSession() {
const session = await trpc.session.getActiveSession.query({
questId: this.questId,
})
async getActiveSession(questId: string) {
const session = await trpc.session.getActiveSession.query({ questId })
if (session) {
this.setSession(session)
await this.setSession(session)
}
},
newUpdate(update: SessionUpdate) {
+17 -2
View File
@@ -1,4 +1,6 @@
<script setup lang="ts">
import { useI18n } from 'vue-i18n'
import { useToast } from 'vue-toastification'
import { computed, onMounted, watch } from 'vue'
import { useSession } from '../store/session'
import useUserProfile from '../store/userProfile'
@@ -13,6 +15,8 @@ import CompleteModal from '../components/game/CompleteModal.vue'
import StartButton from '../components/game/StartButton.vue'
import { openQuestSurvey } from '../utils/formbricks'
const { t, locale } = useI18n()
const toast = useToast()
const sessionStore = useSession()
const userStore = useUserProfile()
@@ -27,6 +31,13 @@ watch(completed, (newValue, oldValue) => {
}
})
watch(locale, (newLocale) => {
const { session } = sessionStore
if (session && newLocale !== session.locale) {
toast.info(t('game.reset_to_apply_language'))
}
})
const props = defineProps({
questId: {
type: String,
@@ -37,8 +48,12 @@ const props = defineProps({
onMounted(async () => {
sessionStore.reset()
sessionStore.setup()
await sessionStore.setQuest(props.questId)
await sessionStore.getActiveSession()
await sessionStore.getActiveSession(props.questId)
if (!sessionStore.session) {
await sessionStore.setQuest(props.questId, locale.value)
}
})
</script>
+7
View File
@@ -16,3 +16,10 @@ export const getSessionsRequestSchema = z.object({
})
export type GetSessionsRequest = z.infer<typeof getSessionsRequestSchema>
export const SUPPORTED_LOCALES = ['zh-TW', 'en'] as const
export const LOCALE_NAME_MAP: Record<string, string> = {
'zh-TW': '繁體中文',
en: 'English',
}
export type QuestLocale = (typeof SUPPORTED_LOCALES)[number]
+8
View File
@@ -1,4 +1,6 @@
import { model, Schema, Types } from 'mongoose'
import type { QuestLocale } from '../constants'
import { SUPPORTED_LOCALES } from '../constants'
export interface INode {
path: string
@@ -27,6 +29,7 @@ export interface ISession {
_id: Types.ObjectId
user: Types.ObjectId
quest: string
locale: QuestLocale
containerId: string | null
containerName: string | null
status: 'active' | 'finished' | 'inactive'
@@ -52,6 +55,11 @@ export const Session = model<ISession>(
ref: 'Quest',
required: true,
},
locale: {
type: String,
enum: SUPPORTED_LOCALES,
required: true,
},
containerId: String,
containerName: String,
status: {
File renamed without changes.
+92
View File
@@ -0,0 +1,92 @@
id: checkpoint-01
title: Checkpoint 1
image: base
instruction: |
This quest tests your understanding of:
1. `echo`: print text
2. `ls`: list the contents of a folder
3. `cd`: move between folders
4. `pwd`: show your current path
requirements:
- path
stages:
- id: start
name: Click `Start` to begin
condition:
command: echo start
response:
content: |
This quest checks what you have learned in the previous lessons.
You will need to choose the commands yourself.
Think about which commands can help you complete each task.
To continue, make the terminal print `next`.
- id: next
name: Make the terminal print `next`
requirements:
- start
condition:
output: next
response:
content: |
Now list the contents of your current folder.
- id: ls-home
name: List the contents of the current folder
requirements:
- next
condition:
pwd: /home/commander
command: ls
response:
content: |
Enter the `folder03` folder.
- id: cd-folder03
name: Enter `folder03`
requirements:
- ls-home
condition:
pwd: /home/commander/folder03
response:
content: |
Show your current path in the terminal.
- id: pwd-folder03
name: Show your current path
requirements:
- cd-folder03
condition:
command: pwd
output: /home/commander/folder03
response:
content: |
Now enter the `folder02` folder
and list its contents.
- id: ls-folder02
name: Enter `folder02` and list its contents
requirements:
- pwd-folder03
condition:
pwd: /home/commander/folder02
command: ls
response:
content: |
Finally, stay in `folder02`
and list the contents of `folder01`.
- id: finish
name: Stay in `folder02` and list the contents of `folder01`
requirements:
- ls-folder02
condition:
pwd: /home/commander/folder02
output: file1.txt
response:
content: |
Congratulations! You passed this checkpoint!
You are ready to move on to the next lessons.
+7
View File
@@ -0,0 +1,7 @@
echo start
echo next
ls
cd folder03
pwd
cd ../folder02
ls ../folder01
File renamed without changes.
File renamed without changes.
+97
View File
@@ -0,0 +1,97 @@
id: checkpoint-02
title: Checkpoint 2
image: base
instruction: |
This quest tests your understanding of:
1. `cat`: display the contents of a file
2. `touch`: create a file
3. `mkdir`: create a folder
4. Use the `Tab` key for autocompletion
5. Topics covered in the previous checkpoint
requirements:
- create
stages:
- id: start
name: Click `Start` to begin
condition:
command: echo start
response:
content: |
This quest checks what you have learned in the previous lessons.
You will need to choose the commands yourself.
Think about which commands can help you complete each task.
To continue, make the terminal print `next`.
- id: next
name: Make the terminal print `next`
requirements:
- start
condition:
output: next
response:
content: |
Now list the contents of your current folder.
- id: ls-home
name: List the contents of the current folder
requirements:
- next
condition:
pwd: /home/commander
command: ls
response:
content: |
Display the contents of `hello.txt`.
- id: cat-hello
name: Display the contents of `hello.txt`
requirements:
- ls-home
condition:
command: cat hello.txt
output: This is `hello.txt`.
response:
content: |
Display the contents of the other file, which has a very long name.
- id: cat-long-filename
name: Display the contents of the other file
requirements:
- cat-hello
condition:
command: cat pneumonoultramicroscopicsilicovolcanoconiosis.txt
output: A name that has been invented for a lung disease caused by breathing in very small pieces of ash or dust.
response:
content: |
Now create a folder named `folder`.
- id: mkdir-folder
name: Create a folder named `folder`
requirements:
- cat-long-filename
condition:
files:
- path: /home/commander/folder
type: directory
exists: true
response:
content: |
Finally, inside the `folder` folder,
create a file named `file.txt`.
- id: finish
name: Create `file.txt` inside `folder`
requirements:
- mkdir-folder
condition:
files:
- path: /home/commander/folder/file.txt
type: file
exists: true
response:
content: |
Congratulations! You passed this checkpoint!
You are ready to move on to the next lessons.
File renamed without changes.
+7
View File
@@ -0,0 +1,7 @@
echo start
echo next
ls
cat hello.txt
cat pneumonoultramicroscopicsilicovolcanoconiosis.txt
mkdir folder
touch folder/file.txt
File renamed without changes.
@@ -0,0 +1 @@
A name that has been invented for a lung disease caused by breathing in very small pieces of ash or dust.
File renamed without changes.
+140
View File
@@ -0,0 +1,140 @@
id: checkpoint-03
title: Checkpoint 3
image: base
instruction: |
This quest tests your understanding of:
1. `cp`: copy files and folders
2. `mv`: move or rename files and folders
3. `rm`: delete files and folders
4. `rmdir`: delete empty folders
5. Use options to change a command's behavior, such as `rm -r`
6. Topics covered in the previous checkpoints
requirements:
- remove
stages:
- id: start
name: Click `Start` to begin
condition:
command: echo start
response:
content: |
This quest checks what you have learned in the previous lessons.
You will need to choose the commands yourself.
Think about which commands can help you complete each task.
To continue, make the terminal print `next`.
- id: next
name: Make the terminal print `next`
requirements:
- start
condition:
output: next
response:
content: |
Now list the contents of your current folder.
- id: ls-home
name: List the contents of the current folder
requirements:
- next
condition:
pwd: /home/commander
command: ls
response:
content: |
Copy the file inside `folder` to a new file named `world.txt` in the same folder.
- id: cp-hello-world
name: Copy the file inside `folder` as `world.txt`
requirements:
- ls-home
condition:
files:
- path: /home/commander/folder/hello.txt
type: file
exists: true
- path: /home/commander/folder/world.txt
type: file
exists: true
response:
content: |
Delete the `hello.txt` file inside `folder`.
- id: rm-hello
name: Delete `hello.txt` inside `folder`
requirements:
- cp-hello-world
condition:
files:
- path: /home/commander/folder/hello.txt
type: file
exists: false
response:
content: |
Now move `world.txt` out of `folder`.
(Move it into your home folder, `/home/commander`.)
- id: mv-world-out
name: Move `world.txt` out of `folder`
requirements:
- rm-hello
condition:
files:
- path: /home/commander/folder/world.txt
type: file
exists: false
- path: /home/commander/world.txt
type: file
exists: true
response:
content: |
Rename `world.txt` back to `hello.txt`
and display its contents.
- id: cat-hello
name: Rename `world.txt` to `hello.txt` and display its contents
requirements:
- mv-world-out
condition:
command: cat hello.txt
files:
- path: /home/commander/world.txt
type: file
exists: false
- path: /home/commander/hello.txt
type: file
exists: true
output: This is `hello.txt`.
response:
content: |
Delete the `folder` folder.
- id: rmdir-folder
name: Delete `folder`
requirements:
- cat-hello
condition:
files:
- path: /home/commander/folder
type: directory
exists: false
response:
content: |
Delete the `trash_can` folder.
- id: finish
name: Delete `trash_can`
requirements:
- rmdir-folder
condition:
files:
- path: /home/commander/trash_can
type: directory
exists: false
response:
content: |
Congratulations! You passed this checkpoint!
You are ready to move on to the next lessons.
@@ -0,0 +1 @@
This is `hello.txt`.
+12
View File
@@ -0,0 +1,12 @@
echo start
echo next
ls
cd folder
cp hello.txt world.txt
rm hello.txt
mv world.txt ..
cd ..
mv world.txt hello.txt
cat hello.txt
rmdir folder
rm -r trash_can
File renamed without changes.
@@ -0,0 +1 @@
This is `hello.txt`.
@@ -0,0 +1 @@
aHR0cHM6Ly9yZXVybC5jYy9YUjZZMDA=
File renamed without changes.
+348
View File
@@ -0,0 +1,348 @@
id: copy
title: Copying Files
image: base
instruction: |
In this quest, you will learn:
1. How to copy files with `cp`
requirements:
- create
stages:
- id: start
name: Click `Start` to begin
condition:
command: echo start
response:
content: |
Today we will learn how to copy files.
First, use `ls` to see which files are in your current folder.
hint: Use `ls` to list the files in your current folder
- id: ls
name: List the files in the current folder
requirements:
- start
condition:
pwd: /home/commander
command: ls
exceptions:
- id: wrong_directory
condition:
not:
pwd: /home/commander
response:
content: |
You are outside the `/home/commander` folder.
Use `cd /home/commander` to return to `/home/commander`.
response:
content: |
You can see `hello.txt` and `world.txt` in this folder.
Use `cat` to display their contents.
When you have finished, enter `echo next` to continue!
hint: |
Use `cat hello.txt` and `cat world.txt` to display the file contents
If a command is keeping the terminal busy, press `Ctrl + C` to cancel it
- id: cat-hello
name: Display the contents of `hello.txt`
requirements:
- ls
condition:
pwd: /home/commander
command: cat hello.txt
output: Hello
exceptions:
- id: wrong_directory
condition:
not:
pwd: /home/commander
response:
content: |
You are outside the `/home/commander` folder.
Use `cd /home/commander` to return to `/home/commander`
- id: missing_command
condition:
command: cat
response:
content: |
To display this file, add its filename after `cat`.
If `cat` is waiting for input, press `Ctrl + C` to cancel it.
Enter `cat hello.txt` to display the contents of `hello.txt`
- id: missing_extension
condition:
command: cat hello
response:
content: |
Did you forget the `.txt` extension?
Enter `cat hello.txt` to display the contents of `hello.txt`
response:
content: |
You have displayed the contents of `hello.txt`!
Here is what it contains:
```
Hello
```
- id: cat-world
name: Display the contents of `world.txt`
requirements:
- ls
condition:
pwd: /home/commander
command: cat world.txt
output: World
exceptions:
- id: wrong_directory
condition:
not:
pwd: /home/commander
response:
content: |
You are outside the `/home/commander` folder.
Use `cd /home/commander` to return to `/home/commander`
- id: missing_command
condition:
command: cat
response:
content: |
To display this file, add its filename after `cat`.
If `cat` is waiting for input, press `Ctrl + C` to cancel it.
Enter `cat world.txt` to display the contents of `world.txt`
- id: missing_extension
condition:
command: cat world
response:
content: |
Did you forget the `.txt` extension?
Enter `cat world.txt` to display the contents of `world.txt`
response:
content: |
You have displayed the contents of `world.txt`!
Here is what it contains:
```
World
```
- id: cat-next
name: Enter `echo next` to continue
requirements:
- cat-hello
- cat-world
condition:
command: echo next
response:
content: |
Next, let's learn how to copy files.
`cp` is short for copy.
To copy a file, use `cp [source file] [destination file]`.
Use `cp` to copy `hello.txt` to `hello2.txt`.
hint: Use `cp hello.txt hello2.txt` to copy `hello.txt` to `hello2.txt`
- id: cp-hello
name: Copy `hello.txt` to `hello2.txt`
requirements:
- cat-next
condition:
pwd: /home/commander
command: cp hello.txt hello2.txt
files:
- path: /home/commander/hello2.txt
type: file
exists: true
exceptions:
- id: wrong_directory
condition:
not:
pwd: /home/commander
response:
content: |
You are outside the `/home/commander` folder.
Use `cd /home/commander` to return to `/home/commander`.
response:
content: |
You have copied `hello.txt` to `hello2.txt`!
Let's check the contents of `hello2.txt`.
hint: Use `cat hello2.txt` to display the contents of `hello2.txt`
- id: cat-hello2
name: Display the contents of `hello2.txt`
requirements:
- cp-hello
condition:
pwd: /home/commander
command: cat hello2.txt
output: Hello
exceptions:
- id: wrong_directory
condition:
not:
pwd: /home/commander
response:
content: |
You are outside the `/home/commander` folder.
Use `cd /home/commander` to return to `/home/commander`.
response:
content: |
You have displayed the contents of `hello2.txt`!
As you can see, `hello2.txt` contains exactly the same text as `hello.txt`.
Now try copying `world.txt` to `world2.txt`!
hint: Use `cp world.txt world2.txt` to copy `world.txt` to `world2.txt`
- id: cp-world
name: Copy `world.txt` to `world2.txt`
requirements:
- cat-hello2
condition:
pwd: /home/commander
command: cp world.txt world2.txt
files:
- path: /home/commander/world2.txt
type: file
exists: true
exceptions:
- id: wrong_directory
condition:
not:
pwd: /home/commander
response:
content: |
You are outside the `/home/commander` folder.
Use `cd /home/commander` to return to `/home/commander`.
response:
content: |
You have copied `world.txt` to `world2.txt`!
Let's check the contents of `world2.txt`.
hint: Use `cat world2.txt` to display the contents of `world2.txt`
- id: cat-world2
name: Display the contents of `world2.txt`
requirements:
- cp-world
condition:
pwd: /home/commander
command: cat world2.txt
output: World
exceptions:
- id: wrong_directory
condition:
not:
pwd: /home/commander
response:
content: |
You are outside the `/home/commander` folder.
Use `cd /home/commander` to return to `/home/commander`.
response:
content: |
You have displayed the contents of `world2.txt`!
`world2.txt` contains exactly the same text as `world.txt`.
Next, let's learn how to copy folders.
Your current folder contains a `notes` folder with a file named `note.txt` inside.
We want to copy the entire folder, including its contents, to `notes2`.
To copy a folder, add the `-r` option (recursive). This copies the folder and everything inside it.
Options let you change how a command behaves.
An option often starts with `-` followed by a letter, such as `-r`.
Options usually go after the command name and before the filenames.
Use `cp -r notes notes2` to copy `notes` to `notes2`.
hint: |
Use `cp -r notes notes2` to copy `notes` to `notes2`
Remember to include `-r` to copy all the contents
- id: cp-notes
name: Copy the `notes` folder to `notes2`
requirements:
- cat-world2
condition:
pwd: /home/commander
command: cp -r notes notes2
files:
- path: /home/commander/notes2
type: directory
exists: true
- path: /home/commander/notes2/note.txt
type: file
exists: true
exceptions:
- id: wrong_directory
condition:
not:
pwd: /home/commander
response:
content: |
You are outside the `/home/commander` folder.
Use `cd /home/commander` to return to `/home/commander`.
- id: missing_recursive
condition:
command: cp notes notes2
response:
content: |
Did you forget the `-r` option?
Enter `cp -r notes notes2` to copy `notes` to `notes2`
response:
content: |
You have copied the `notes` folder to `notes2`!
The entire `notes` folder, including its files, has been copied to `notes2`.
`cp -r` copies everything in a folder, including files inside any nested folders.
Finally, let's see what happens when you copy a file to a destination that already exists.
Copy `hello.txt` to `world.txt` and see what happens.
hint: Use `cp hello.txt world.txt` to copy `hello.txt` to `world.txt`
- id: cp-overwrite
name: Copy `hello.txt` to `world.txt`
requirements:
- cp-notes
condition:
pwd: /home/commander
command: cp hello.txt world.txt
exceptions:
- id: wrong_directory
condition:
not:
pwd: /home/commander
response:
content: |
You are outside the `/home/commander` folder.
Use `cd /home/commander` to return to `/home/commander`.
response:
content: |
You have copied `hello.txt` to `world.txt`!
Let's check the contents of `world.txt`.
hint: Use `cat world.txt`
- id: check-world
name: Check the contents of `world.txt`
requirements:
- cp-overwrite
condition:
pwd: /home/commander
command: cat world.txt
output: Hello
exceptions:
- id: wrong_directory
condition:
not:
pwd: /home/commander
response:
content: |
You are outside the `/home/commander` folder.
Use `cd /home/commander` to return to `/home/commander`.
response:
content: |
`world.txt` now contains `Hello`!
When the destination file already exists, copying another file to it overwrites its contents.
Check whether the destination already exists before copying, so you do not accidentally lose data.
That covers the basics of copying files!
Enter `echo finish` to complete this quest.
- id: finish
name: Congratulations! All tasks completed!
requirements:
- check-world
condition:
command: echo finish
response:
content: |
Congratulations! You have completed all the tasks!
You now know how to copy files and folders.
In the next quest, you will learn how to move files and folders.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+13
View File
@@ -0,0 +1,13 @@
echo start
ls
cat hello.txt
cat world.txt
echo next
cp hello.txt hello2.txt
cat hello2.txt
cp world.txt world2.txt
cat world2.txt
cp -r notes notes2
ls notes2
cp hello.txt world.txt
cat world.txt
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+165
View File
@@ -0,0 +1,165 @@
id: create
title: Creating Files and Folders
image: base
instruction: |
In this quest, you will learn:
1. How to create files with `touch`
2. How to create folders with `mkdir`
requirements:
- tab
stages:
- id: start
name: Click `Start` to begin
condition:
command: echo start
response:
content: |
This time, we will learn about the `touch` command.
First, use `ls` to list the files in your current folder.
You should find that the folder has no files.
hint: Enter `ls` to list the files in your current folder
- id: ls
name: List the files in the folder
requirements:
- start
condition:
command: ls
response:
content: |
The terminal shows no output, which means there are no visible files in this folder.
You can create a file with `touch [filename]`.
Try creating a file named `hello.txt` in the terminal.
hint: Enter `touch hello.txt` to create a file
- id: touch
name: Create a file with `touch`
requirements:
- ls
condition:
files:
- path: /home/commander/hello.txt
type: file
exists: true
exceptions:
- id: missing_extension
condition:
files:
- path: /home/commander/hello
type: file
exists: true
response:
content: |
It looks like you forgot the `.txt` extension.
Try again and make sure the filename is `hello.txt`.
response:
content: |
The terminal should show no output.
The file tree on the right now shows the new `hello.txt` file.
Let's look inside `hello.txt`!
Use the `cat` command you learned earlier to display its contents.
hint: Enter `cat hello.txt` to display the contents of `hello.txt`
- id: cat
name: Display the contents of `hello.txt` with `cat`
requirements:
- touch
condition:
command: cat hello.txt
response:
content: |
Huh? There is nothing there!
That's right. A new file created with `touch` is empty.
We will learn how to edit file contents in a future lesson.
Let's create another file!
Try creating another file named `world.txt` in the terminal.
hint: Enter `touch world.txt` to create a file
- id: touch-2
name: Create another file named `world.txt` with `touch`
requirements:
- cat
condition:
files:
- path: /home/commander/world.txt
type: file
exists: true
exceptions:
- id: missing_extension
condition:
files:
- path: /home/commander/world
type: file
exists: true
response:
content: |
It looks like you forgot the `.txt` extension.
Try again and make sure the filename is `world.txt`.
response:
content: |
Great! You have created your second file.
The file tree now shows both `hello.txt` and `world.txt`.
Next, let's create a folder!
The `mkdir` command creates an empty folder.
Use `mkdir [folder name]`.
Try creating a folder named `notes` in the terminal.
hint: Enter `mkdir notes` to create a folder
- id: mkdir
name: Create the `notes` folder with `mkdir`
requirements:
- touch-2
condition:
files:
- path: /home/commander/notes
type: directory
exists: true
response:
content: |
Great! You have created the `notes` folder.
Next, we will create a file named `note.txt` inside `notes`.
First, enter the `notes` folder.
Remember the `cd` command? Try using it to enter `notes`.
hint: |
Enter `cd notes` to enter the `notes` folder
After typing `cd n`, press `Tab` to complete the folder name
- id: cd-notes
name: Enter the `notes` folder
requirements:
- mkdir
condition:
pwd: /home/commander/notes
response:
content: |
You have entered the `notes` folder.
Now try creating a file named `note.txt` inside `notes`.
hint: Enter `touch note.txt` to create a file
- id: touch-note
name: Create `note.txt` inside `notes`
requirements:
- cd-notes
condition:
files:
- path: /home/commander/notes/note.txt
type: file
exists: true
response:
content: |
Great! You have created `note.txt`.
Congratulations! You have completed this quest!
In the next quest, you will learn how to copy files and folders.
Enter `echo finish` to complete this quest.
- id: END
name: Complete the quest
requirements:
- touch-note
condition:
command: echo finish
response:
content: |
Congratulations! You have completed this quest!
+12
View File
@@ -0,0 +1,12 @@
echo start
ls
touch hello.txt
ls
cat hello.txt
touch world.txt
ls
mkdir notes
ls
cd notes
touch note.txt
ls
File renamed without changes.
+79
View File
@@ -0,0 +1,79 @@
# Running Executable Files
## Outline
1. What an executable file is
2. How to find an executable with `which`
3. How to run an executable file
---
In earlier lessons, you used commands such as `ls`, `cat`, `cp`, `mv`, and `rm`.
These commands are **executable files** that the operating system runs when you enter them.
For most commands, you can find the corresponding file in the file system.
Use `which` to find the file associated with a command.
Enter `which [command name]` to display its path.
> Use `which ls` to find the path to `ls`
---
The terminal displays `/usr/bin/ls`, the location of the `ls` executable.
`/usr/bin` is a system folder containing many standard programs, including commands such as `cat` and `cp`.
> Use `which cat` to find the path to `cat`
---
To run an executable file, enter its path directly.
Let's try running a command using the path to its executable.
> Enter `/usr/bin/ls` to list the contents of your current folder
---
It lists the files in your folder, just as entering `ls` does. You can compare the results yourself.
You can still pass arguments. Let's try this with `cat`.
> Enter `/usr/bin/cat hello.txt` to display the contents of `hello.txt`
---
You can see the contents of `hello.txt`, just as you would with `cat`.
This makes sense: `cat` is located at `/usr/bin/cat`, so both commands run the same program.
A command like this consists of **an executable** plus **arguments**.
You can enter `ls` instead of `/usr/bin/ls` because the `PATH` environment variable tells the terminal which *folders* to search for programs.
`PATH` and environment variables are beyond this lesson's scope. We will cover them in a future lesson.
You can also run custom programs, such as the `dog` file in your current folder.
> Use `cat dog` to display the contents of `dog`
---
This is a simple program built from `echo` and `sleep` commands.
You do not need to understand every detail yet. It prints a few lines of text, with short pauses between them.
To run a file, specify its path.
Since `dog` is in your home folder, its absolute path is `/home/commander/dog`. You can also use the shorter form `~/dog`.
> Enter `~/dog` to run the `dog` file
---
The terminal displays a few words from this dog with an attitude.
When you are in the same folder as a program, a relative path is often more convenient than an absolute path.
To run a program in your current folder, put `./` before its filename instead of entering just its name.
In a path, `.` means the current folder.
Now try running `dog` using a relative path.
> Enter `./dog` to run the `dog` file
---
The dog produces the same output as before.
This is an example of a simple custom command.
You can put a sequence of commands in a file and run them together to handle complex or repetitive tasks.
This technique is also useful when running programs written by other people.
Here is a final challenge: enter the `commands` folder, then run the `lucky` file inside it using a relative path.
+236
View File
@@ -0,0 +1,236 @@
id: execute
title: Running Executable Files
image: base
instruction: |
In this quest, you will learn:
1. What an executable file is
2. How to find an executable with `which`
3. How to run an executable file
requirements:
- remove
stages:
- id: start
name: Click Start
condition:
command: echo start
response:
content: |
In earlier lessons, you used commands such as `ls`, `cat`, `cp`, `mv`, and `rm`.
These commands are **executable files** that the operating system runs when you enter them.
For most commands, you can find the corresponding file in the file system.
Use `which` to find the file associated with a command.
Enter `which [command name]` to display its path.
hint: Use `which ls` to find the path to `ls`
- id: which-ls
name: Find the path to `ls` with `which`
requirements:
- start
condition:
command: which ls
response:
content: |
The terminal displays `/usr/bin/ls`, the location of the `ls` executable.
`/usr/bin` is a system folder containing many standard programs.
Next, let's find the path to `cat`.
hint: Use `which cat` to find the path to `cat`
- id: which-cat
name: Find the path to `cat` with `which`
requirements:
- which-ls
condition:
command: which cat
response:
content: |
You can see `/usr/bin/cat`, which is also in the `/usr/bin` folder.
To run an executable file, **enter its path directly**.
Let's try running a command using the path to its executable.
First, let's see what happens when you run `ls` normally.
hint: Enter `ls` to list the contents of your current folder
- id: ls
name: List the current folder with `ls`
requirements:
- which-cat
condition:
command: ls
response:
content: |
Your current folder contains the `commands` folder and two files, `dog` and `hello.txt`.
Now try running `ls` using its absolute path, `/usr/bin/ls`.
hint: Enter `/usr/bin/ls` to list the contents of your current folder
- id: bin-ls
name: Run `ls` using its absolute path
requirements:
- ls
condition:
command: /usr/bin/ls
exceptions:
- id: exception-ls
condition:
command: ls
response:
content: |
Here, we are practicing running `ls` using its absolute path.
Enter `/usr/bin/ls` to list the contents of your current folder.
response:
content: |
It lists the same files as `ls`. Both commands run the program at `/usr/bin/ls`, so the results are the same.
You can still pass arguments. Try using `/usr/bin/cat` to display the contents of `hello.txt`.
hint: Enter `/usr/bin/cat hello.txt`
- id: bin-cat
name: Run `cat` using its absolute path
requirements:
- bin-ls
condition:
command: /usr/bin/cat hello.txt
response:
content: |
You can see the contents of `hello.txt`, just as you would with `cat`.
Both commands run the program at `/usr/bin/cat`, so the results are the same.
A command usually has the form `command argument1 argument2 ...`.
The `command` is the name or path of the program to run, such as `ls`, `cat`, or `which`.
The `arguments` provide information to the program, such as `hello.txt` after `cat`.
You can enter `ls` instead of `/usr/bin/ls` because an environment variable called `PATH` tells the shell which folders to search for programs.
We will learn more about `PATH` in a future lesson.
Now let's try running a custom command.
The file named `dog` in this folder is a custom command provided for this lesson.
First, let's see what is written inside it.
hint: Use `cat dog` to display the contents of `dog`
- id: cat-dog
name: Display the contents of `dog` with `cat`
requirements:
- bin-cat
condition:
command: cat dog
response:
content: |
This is a simple program built from `echo` and `sleep` commands.
You do not need to understand every detail yet. It just prints a few lines of text.
To run a file, specify its path.
Here, the first part of the command is the path to `dog`. This example does not use any arguments.
Since `dog` is in your home folder, its absolute path is `/home/commander/dog`.
Using the format `executable arguments`, the command is:
```
/home/commander/dog
```
hint: Enter `/home/commander/dog` to run the `dog` file
- id: dog-abs
name: Run `dog` using an absolute path
requirements:
- cat-dog
condition:
or:
- command: /home/commander/dog
- command: ~/dog
exceptions:
- id: exception-dog
condition:
command: dog
error: 'command not found: dog'
response:
content: |
`dog` cannot be run by name here because it is not in the command search path. Specify the path to its executable file.
Here, we are practicing running `dog` using an absolute path.
Enter `/home/commander/dog` to run the `dog` file.
response:
content: |
The terminal displays a few words from this dog with an attitude.
When you are in the same folder as a program, a relative path is often more convenient than an absolute path.
To run a program in your current folder, put `./` before its filename instead of entering just its name.
In a path, `.` means the current folder.
Now try running `dog` using a relative path.
hint: Enter `./dog` to run the `dog` file
- id: dog-rel
name: Run `dog` using a relative path
requirements:
- dog-abs
condition:
pwd: /home/commander
command: ./dog
exceptions:
- id: exception-dog-2
condition:
command: dog
error: 'command not found: dog'
response:
content: |
`dog` cannot be run by name here because it is not in the command search path. Specify the path to its executable file.
Here, we are practicing running `dog` using a relative path.
Enter `./dog` to run the `dog` file.
response:
content: |
The dog produces the same output as before.
This is an example of a simple custom command.
You can put a sequence of commands in a file and run them together to handle complex or repetitive tasks.
This technique is also useful when running programs written by other people.
Here is a final challenge: enter the `commands` folder, then run the `lucky` file inside it using a relative path.
hint: |
Use `cd` to enter a folder
Use `ls` to list the files
Enter `./filename` to run a file
- id: execute-lucky
name: Run `lucky` using a relative path
requirements:
- dog-rel
condition:
pwd: /home/commander/commands
command: ./lucky
response:
content: |
The terminal displays `I am SO LUCKY!!!`, the message printed by `lucky`.
Congratulations! You have completed this lesson!
Enter `echo finish` to complete this quest.
exceptions:
- id: exception-lucky
condition:
command: lucky
error: 'command not found: lucky'
response:
content: |
`lucky` cannot be run by name here because it is not in the command search path. Specify the path to its executable file.
- id: exception-lucky-2
condition:
pwd: /home/commander
command: ./lucky
error: 'no such file or directory'
response:
content: |
You are outside the `commands` folder, so `./lucky` does not point to the file yet.
First, enter `cd commands` to move into `commands`. Then enter `./lucky` to run `lucky` using a relative path.
- id: help
condition:
command: echo help
response:
content: |
Enter the `commands` folder before running `lucky` using a relative path.
First, enter `cd commands` to move into `commands`. Then enter `./lucky` to run `lucky` using a relative path.
- id: END
name: Congratulations! All tasks completed!
requirements:
- execute-lucky
condition:
command: echo finish
response:
content: |
Congratulations! You have completed this lesson!
You now know how to run executable files.
File renamed without changes.
+8
View File
@@ -0,0 +1,8 @@
#!/bin/sh
echo "You ran the dog file"
echo "Woof woof woof"
sleep 1
echo "You know what?"
sleep 1
echo "I am better than a cat"
File renamed without changes.
File renamed without changes.
File renamed without changes.
+3
View File
@@ -0,0 +1,3 @@
#!/bin/sh
echo "I am SO LUCKY!!!"
File renamed without changes.
+1
View File
@@ -0,0 +1 @@
Hello! This is a file hello.txt
File renamed without changes.
+161
View File
@@ -0,0 +1,161 @@
id: explore
image: base
title: Exploring Files
instruction: |
In this quest, you will learn:
1. How to list folder contents with `ls`
2. How to move between folders with `cd`
requirements:
- get-started
stages:
- id: start
name: Click `Start` to begin the lesson
condition:
command: ^echo start$
response:
content: |
The terminal has no graphical interface for browsing folder contents.
Instead, you can use `ls` to list what is inside a folder.
`ls` is short for list. Its first character is a lowercase L.
When you enter `ls`, the terminal lists the files and folders in your current folder.
Now enter `ls` to see what is in this folder.
hint: Enter `ls` to list the contents of the folder
- id: ls
name: List the files in the folder
requirements:
- start
condition:
command: ^ls$
exceptions:
- id: wrong_directory
condition:
not:
pwd: /home/commander
response:
type: narrative
content: |
First, return to `/home/commander/`
Enter `cd ~` to return to `/home/commander/`
response:
content: |
You should now see the contents of the folder.
The file tree on the right has changed too.
This folder contains two folders named `folder1` and `folder2`.
Next, let's learn how to enter a folder.
`cd` is short for change directory, which means changing your current folder.
Enter `cd [folder name]` to move into a folder.
For example, enter `cd folder1` to move into `folder1`.
Now enter the `folder1` folder.
hint: Enter `cd folder1` to move into `folder1`
- id: cd-folder1
name: Enter `folder1`
requirements:
- ls
condition:
pwd: /home/commander/folder1
exceptions:
- id: wrong_spelling
condition:
command: ^folderl$
response:
type: narrative
content: |
`folder1` ends with the number `1`, not the letter `l`.
- id: wrong_directory
condition:
pwd: /home/commander
response:
type: narrative
content: Enter `cd folder1` to move into `folder1`
- id: not_in_home
condition:
not:
pwd: /home/commander
response:
type: narrative
content: |
First, return to `/home/commander/`
Enter `cd ~` to return to `/home/commander/`
Then enter `cd folder1` to move into `folder1`
response:
content: |
You have entered the `folder1` folder.
Notice that the command prompt has changed from
`commander:~ $` to
`commander:~/folder1 $`.
This tells you that you are now in `folder1`.
Now list the contents of `folder1`.
hint: Enter `ls` to list the contents of the folder
- id: ls-folder1
name: List the contents of `folder1`
requirements:
- cd-folder1
condition:
pwd: /home/commander/folder1
command: ^ls$
response:
content: |
You can see two files in `folder1`, named `file1.txt` and `file2.txt`.
Now let's leave `folder1` and return to the original folder.
Use `cd ..` to move up to the parent folder.
Here, `..` means the parent folder.
hint: Enter `cd ..` to move up to the parent folder
- id: cd_up
name: Return to the parent folder
requirements:
- ls-folder1
condition:
pwd: /home/commander
response:
content: |
You have returned to the parent folder.
Use the commands you just learned to enter `folder2`, list its contents, and return to this folder.
hint: |
Use `cd` to move between folders
Use `ls` to list the contents of a folder
- id: cd-folder2
name: Enter `folder2`
requirements:
- cd_up
condition:
pwd: /home/commander/folder2
response:
content: |
You have entered the `folder2` folder.
Now list the contents of `folder2`.
hint: Use `ls` to list the contents of the folder
- id: ls-folder2
name: List the contents of `folder2`
requirements:
- cd-folder2
condition:
pwd: /home/commander/folder2
command: ^ls$
response:
content: |
You can see two files in `folder2`, named `file3.txt` and `file4.txt`.
Now leave `folder2` and return to the original folder.
hint: Use `cd ..` to move up to the parent folder
- id: END
name: Return to the original folder
requirements:
- ls-folder2
condition:
pwd: /home/commander
response:
content: |
You have returned to the original folder.
Congratulations! You now know how to use `ls` and `cd`.
hint: |
Use `cd` to move between folders
Use `ls` to list the contents of a folder
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+8
View File
@@ -0,0 +1,8 @@
echo start
ls
cd folder1
ls
cd ..
cd folder2
ls
cd ..
File renamed without changes.
Whitespace-only changes.
Whitespace-only changes.
File renamed without changes.
+76
View File
@@ -0,0 +1,76 @@
id: get-started
image: base
title: Terminal Basics
instruction: |
Welcome to Linux Odyssey!
This quest introduces the basics of using the terminal.
In this quest, you will learn:
1. How to use this website
2. How to use the terminal
3. How to use the `echo` command
stages:
- id: start
name: Click `Start` to begin
condition:
command: ^echo start$
response:
content: |
Hello, brave adventurer!
Welcome to Linux Odyssey, an adventure filled with terminal magic!
Think of the terminal as your magic wand. You control the computer with **text spells**, a useful skill for any aspiring programmer!
The area below is your stage for casting spells: the terminal. Ready to cast your first one?
Enter `echo hello` below, then press Enter to see what happens!
- id: echo-hello
name: Enter `echo hello` in the terminal
requirements:
- start
condition:
command: ^echo hello$
response:
content: |
Congratulations on running your first command!
You should see this in the terminal:
```
commander:~ $ echo hello
hello
```
The prompt `commander:~ $` means the computer is waiting for a command.
After you enter `echo hello`, the computer prints "hello" on the next line.
A command is like a sentence telling the computer what to do.
Take `echo hello`, for example:
- `echo` tells the computer to print something
- `hello` is the text to print
So when you enter `echo hello`, the computer prints "hello".
Now try making the terminal display the text `next`.
If you get stuck, click the `Hint` button for help.
hint: |
Enter `echo next` to continue to the next step.
- id: echo-next
name: Enter `echo next` in the terminal
requirements:
- echo-hello
condition:
command: ^echo next$
response:
content: |
Congratulations! You now know how to use `echo`.
You might wonder why we need a command like this.
Although `echo` is simple, printing text is a basic building block for many tasks.
In this adventure, we will also use `echo` to trigger events.
That is all for this quest. Enter `echo finish` to complete it.
- id: END
name: Finish the quest
requirements:
- echo-next
condition:
command: ^echo finish$
response:
content: |
Congratulations! You have completed this quest!
You have learned how to use `echo` and what it does.
+4
View File
@@ -0,0 +1,4 @@
echo start
echo hello
echo next
echo finish
File renamed without changes.
File renamed without changes.
+136
View File
@@ -0,0 +1,136 @@
id: move
title: Moving Files
image: base
instruction: |
In this quest, you will learn:
1. How to move files and folders with `mv`
requirements:
- create
stages:
- id: start
name: Click `Start` to begin
condition:
command: echo start
response:
content: |
Today we will learn how to move files and folders.
Your current folder contains `hello.txt`, `world.txt`, and a folder named `notes`.
First, use `ls` and `cat` to explore their contents.
When you have finished, enter `echo next` to continue!
hint: |
Use `ls` and `ls notes` to list the files in the folders
Use `cat hello.txt` and `cat world.txt` to display the file contents
When you have finished, enter `echo next` to continue
- id: next
requirements:
- start
name: Explore the files, then enter `echo next` to continue
condition:
command: echo next
response:
content: |
Now let's learn how to move files and folders.
`mv` is short for move. It moves files and folders.
Use `mv [source] [destination]`.
Let's start by moving `hello.txt` into the `notes` folder!
hint: Use `mv hello.txt notes` to move `hello.txt` into `notes`
- id: mv-hello
requirements:
- next
name: Move `hello.txt` into `notes`
condition:
command: mv hello.txt notes
files:
- path: /home/commander/notes/hello.txt
type: file
exists: true
- path: /home/commander/hello.txt
type: file
exists: false
response:
content: |
Well done!
`hello.txt` has been moved into `notes`!
`mv` can also rename files!
Just use the new name as the destination.
Now rename `world.txt` to `wow.txt`.
hint: Use `mv world.txt wow.txt` to rename `world.txt` to `wow.txt`
- id: mv-world
requirements:
- mv-hello
name: Rename `world.txt` to `wow.txt`
condition:
command: mv world.txt wow.txt
files:
- path: /home/commander/wow.txt
type: file
exists: true
- path: /home/commander/world.txt
type: file
exists: false
response:
content: |
`world.txt` is now named `wow.txt`.
Next, let's learn how to move folders!
Moving a folder works the same way as moving a file.
`mv` automatically moves everything inside the folder too.
First, rename the `notes` folder to `docs`!
hint: Use `mv notes docs` to rename `notes` to `docs`
- id: mv-notes
requirements:
- mv-world
name: Rename `notes` to `docs`
condition:
command: mv notes docs
files:
- path: /home/commander/docs
type: directory
exists: true
- path: /home/commander/notes
type: directory
exists: false
response:
content: |
The `notes` folder is now named `docs`.
Here is a final challenge:
Move `docs/hello.txt` to your home folder and rename it to `hi.txt`.
hint: Use `mv docs/hello.txt hi.txt` to move the file to your home folder as `hi.txt`
- id: mv-docs-hello
requirements:
- mv-notes
name: Move `docs/hello.txt` to your home folder as `hi.txt`
condition:
command: mv docs/hello.txt hi.txt
files:
- path: /home/commander/hi.txt
type: file
exists: true
- path: /home/commander/docs/hello.txt
type: file
exists: false
response:
content: |
Well done!
You now know how to move files and folders!
Enter `echo finish` to complete this quest.
- id: END
requirements:
- mv-docs-hello
name: Complete the quest
condition:
command: echo finish
response:
content: |
You now know how to move files and folders!
Congratulations on completing this quest!
File renamed without changes.
File renamed without changes.
File renamed without changes.
+11
View File
@@ -0,0 +1,11 @@
echo start
echo next
mv hello.txt notes
ls
ls notes
echo next
mv world.txt wow.txt
ls
mv notes docs
ls
mv docs/hello.txt hi.txt
File renamed without changes.
+1
View File
@@ -0,0 +1 @@
Hello
+1
View File
@@ -0,0 +1 @@
Note
+1
View File
@@ -0,0 +1 @@
World
File renamed without changes.
+146
View File
@@ -0,0 +1,146 @@
id: path
title: File Paths
image: base
instruction: |
In this quest, you will learn:
1. Absolute and relative paths
2. How to show your current path with `pwd`
requirements:
- explore
stages:
- id: start
name: Click `Start` to begin the lesson
condition:
command: echo start
response:
content: |
In Linux, a path describes the location of a file or folder.
Paths can be relative or absolute.
A relative path starts from your current folder. An absolute path starts from the root folder.
First, use `ls` to list the files in this folder.
- id: ls
name: List the files in the folder
requirements:
- start
condition:
pwd: /home/commander
command: ls
response:
content: |
Now use `cd` to enter the `folder1` folder.
- id: cd-folder1
name: Enter `folder1`
requirements:
- ls
condition:
pwd: /home/commander/folder1
response:
content: |
You have entered `folder1`.
In `cd folder1`, the `folder1` part is a relative path.
Likewise, `..` in `cd ..` is a relative path.
A relative path can span more than one level of folders.
For example, to enter `folder2` from here, you could use `cd ..` to go up one level, then `cd folder2` to enter it.
You can also join `..` and `folder2` with `/` and enter `cd ../folder2` to get there in one command.
Try entering `folder2` this way.
hint: Enter `cd ../folder2` to move into `folder2`.
- id: cd-folder2
name: Enter `folder2`
requirements:
- cd-folder1
condition:
pwd: /home/commander/folder2
exceptions:
- id: not_in_folder2
condition:
pwd: /home/commander
response:
content: Enter `cd folder2` to move into `folder2`
response:
content: |
You have entered `folder2` using a relative path.
You can also add a relative path after `ls` to list the contents of another folder.
For example, use `ls ../folder1` to see which files are in `folder1`.
Try listing the files in `folder1` this way.
hint: Enter `ls ../folder1` to list the files in `folder1`.
- id: ls-folder1
name: List the files in `folder1`
requirements:
- cd-folder2
condition:
output: file1.txt
exceptions:
- id: not_in_folder2
condition:
not:
pwd: /home/commander/folder2
response:
content: Return to `folder2` with `cd ~/folder2`, then use `ls ../folder1` to list the contents of `folder1` without leaving `folder2`.
response:
content: |
Great! You now know how to use relative paths.
Next, let's look at absolute paths.
An absolute path starts from the root folder, which is at the top of the file tree.
Use `pwd` to display the absolute path to your current folder.
`pwd` stands for `print working directory`: it displays the path to the folder you are in.
Now use `pwd` to display your current absolute path.
hint: Enter `pwd` to display your current absolute path
- id: pwd
name: Display your current absolute path
requirements:
- ls-folder1
condition:
pwd: /home/commander/folder2
command: pwd
exceptions:
- id: not_in_folder2
condition:
not:
pwd: /home/commander/folder2
response:
content: Return to `folder2`, then use `pwd` to display your current absolute path
response:
content: |
Your current absolute path is `/home/commander/folder2`.
The command prompt also shows your current location.
In `commander:~/folder2 $`, `~/folder2` is a shortened form of the path to your current folder.
`~` stands for `/home/commander`, your home folder. Each game starts here.
You can use absolute paths with `ls` and `cd` too.
For example, use `ls ~` to list your home folder or `cd ~` to return to it.
Now use `ls ~` to list the contents of your home folder.
hint: Enter `ls ~` to list the contents of your home folder
- id: ls_home
name: List the contents of your home folder
requirements:
- pwd
condition:
command: ls ~
response:
content: |
Now use `cd ~` to return to your home folder.
hint: Enter `cd ~` to return to your home folder
- id: END
name: Return to your home folder
requirements:
- ls_home
condition:
command: cd ~
exceptions:
- id: already_home
condition:
pwd: /home/commander
response:
content: Use `cd ~` to return to your home folder
response:
content: |
You have returned to your home folder.
Congratulations! You now know how to use absolute and relative paths and display your current absolute path.
Whitespace-only changes.
Whitespace-only changes.
Whitespace-only changes.
Whitespace-only changes.
+8
View File
@@ -0,0 +1,8 @@
echo start
ls
cd folder1
cd ../folder2
ls ../folder1
pwd
ls ~
cd ~
Loaded 100 of 154 files, more files were not shown because too many files have changed in this diff. Show more