mirror of
https://github.com/linux-odyssey/linux-odyssey.git
synced 2026-11-05 19:20:12 +08:00
Feature/multilingual quests (#209)
This commit is contained in:
154 files changed
+2712
-108
No files matched your search
@@ -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,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) => {
|
||||
|
||||
@@ -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' })
|
||||
|
||||
@@ -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>
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
@@ -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": "此關卡不支援所選語言,請選擇其他語言"
|
||||
}
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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]
|
||||
@@ -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.
@@ -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.
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,7 @@
|
||||
echo start
|
||||
echo next
|
||||
ls
|
||||
cd folder03
|
||||
pwd
|
||||
cd ../folder02
|
||||
ls ../folder01
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -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.
File renamed without changes.
@@ -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.
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.
@@ -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`.
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -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`.
|
||||
File renamed without changes.
File renamed without changes.
@@ -0,0 +1 @@
|
||||
aHR0cHM6Ly9yZXVybC5jYy9YUjZZMDA=
|
||||
File renamed without changes.
File renamed without changes.
@@ -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.
@@ -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.
@@ -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!
|
||||
@@ -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.
@@ -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.
|
||||
@@ -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.
|
||||
Executable → Regular
File renamed without changes.
@@ -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.
Executable
+3
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "I am SO LUCKY!!!"
|
||||
File renamed without changes.
@@ -0,0 +1 @@
|
||||
Hello! This is a file hello.txt
|
||||
File renamed without changes.
@@ -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.
@@ -0,0 +1,8 @@
|
||||
echo start
|
||||
ls
|
||||
cd folder1
|
||||
ls
|
||||
cd ..
|
||||
cd folder2
|
||||
ls
|
||||
cd ..
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
Whitespace-only changes.
Whitespace-only changes.
File renamed without changes.
@@ -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.
|
||||
@@ -0,0 +1,4 @@
|
||||
echo start
|
||||
echo hello
|
||||
echo next
|
||||
echo finish
|
||||
File renamed without changes.
File renamed without changes.
@@ -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.
@@ -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.
@@ -0,0 +1 @@
|
||||
Hello
|
||||
@@ -0,0 +1 @@
|
||||
Note
|
||||
@@ -0,0 +1 @@
|
||||
World
|
||||
File renamed without changes.
@@ -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.
@@ -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
Reference in new issue
Block a user