Write robust shell: loops, parsing, exit codes and small automation.
- Bash Strict Mode Headereasy · in-browser
Write /home/player/strict.sh, a script that opens with the unofficial Bash strict-mode header. The first line must be the shebang #!/usr/bin/env bash. Then enable strict mode with `set -euo pipefail`, and set IFS to a safe value (a newline and tab) with an `IFS=` assignment (e.g. IFS=$'
\t').
(Authored config, graded structurally — the engine isn't run here.)
- Compute a factorialeasy
Write /home/player/fact.sh that prints N! for the integer in $1 (fact.sh 0 -> 1, fact.sh 5 -> 120).
- Count argumentseasy
Write /home/player/argc.sh that prints how many arguments it got.
- Count downeasy
Write /home/player/cd.sh that prints N down to 1, one per line (N in $1).
- Count words in a fileeasy
Write /home/player/cw.sh that prints the number of whitespace-separated words in the file named by $1.
- Iterate a Bash Arrayeasy · in-browser
Write /home/player/fruits.sh (shebang #!/bin/bash) that defines an indexed array with `name=(...)`, iterates over every element with a `for` loop over "${arr[@]}", and finally prints the number of elements using ${#arr[@]}.
(Authored config, graded structurally — the engine isn't run here.)
- Largest argumenteasy
Write /home/player/max.sh that prints the largest of its integer arguments.
- Make a runnable scripteasy
Create /home/player/greet.sh that prints `hello <first arg>`, and make it directly executable so `/home/player/greet.sh world` prints `hello world`.
- Reverse a file's lineseasy
Write /home/player/rev.sh that, given a file path in $1, prints its lines in reverse order (last line first).
- Reverse a stringeasy
Write /home/player/rev.sh that prints $1 reversed.
- Service Control with case/esaceasy · in-browser
Write /home/player/svc.sh (shebang #!/bin/bash) that dispatches on its first argument ($1) using a `case` statement. Handle the subcommands `start`, `stop` and `restart`, include a default `*)` branch for anything else, and close the block with `esac`.
(Authored config, graded structurally — the engine isn't run here.)
- Sum the argumentseasy
Write /home/player/sum.sh that prints the integer sum of all its arguments. With no arguments it must print 0.
- Timestamped Logging Helpereasy · in-browser
Write /home/player/logger.sh whose first line is the env-bash shebang #!/usr/bin/env bash. Define a `log()` function that timestamps each message with `date`, formats the line with `printf` using a `%s` specifier, and writes to standard error by redirecting with >&2.
(Authored config, graded structurally — the engine isn't run here.)
- Uppercase a wordeasy
Write /home/player/up.sh that prints $1 in UPPERCASE.
- Usage Function and Argument Guardeasy · in-browser
Write /home/player/backup.sh that starts with a #!/bin/bash shebang, defines a `usage` function printing how to call the script, and guards its arguments: if fewer than one argument was given (test `$# -lt 1`) it must call usage and `exit 1`.
(Authored config, graded structurally — the engine isn't run here.)
- Average with Integer Arithmeticmedium · in-browser
Write /home/player/average.sh (shebang #!/bin/bash) that averages its numeric arguments using Bash arithmetic. Accumulate the running total inside (( ... )) with a `+=` step, then compute the integer average with a division inside (( ... )) and print it.
(Authored config, graded structurally — the engine isn't run here.)
- Batch-rename by extensionmedium
Write /home/player/ren.sh that, given a directory in $1, renames every *.txt file in it to the same name with a .bak extension instead (contents preserved). Other files are left alone.
- Classic FizzBuzzmedium
Write /home/player/fb.sh that, given N in $1, prints 1..N one per line — but multiples of 3 print Fizz, of 5 print Buzz, of 15 print FizzBuzz.
- Count matchesmedium
Write /home/player/cnt.sh PATTERN FILE printing how many lines of FILE contain PATTERN.
- Default a missing argumentmedium
Write /home/player/who.sh that prints $1, or the literal 'anonymous' when called with no argument.
- Defaulted and Required Parametersmedium · in-browser
Write /home/player/run.sh (shebang #!/bin/bash) that uses parameter expansion to configure itself from the environment. Give PORT a fallback with ${PORT:-8080}, and make HOST mandatory with ${HOST:?...} so the script aborts with a message if HOST is unset or empty.
(Authored config, graded structurally — the engine isn't run here.)
- Function Returning an Exit Statusmedium · in-browser
Write /home/player/isfile.sh (shebang #!/bin/bash) that defines a shell function (NAME() { ... }) which tests its first argument with an `if [[ ]]` conditional (e.g. -r for readable) and signals the result by `return`-ing an explicit 0 or 1 status to the caller.
(Authored config, graded structurally — the engine isn't run here.)
- Generate a Config with a Here-Documentmedium · in-browser
Write /home/player/gen-config.sh (shebang #!/bin/bash) that writes a multi-line config file using a here-document. Redirect a `cat` into the target file (cat > "$out"), open the body with an UPPERCASE delimiter such as `<<EOF`, and close it with that same bare uppercase delimiter word alone on its own line.
(Authored config, graded structurally — the engine isn't run here.)
- Greatest common divisormedium
Write /home/player/gcd.sh that prints gcd($1,$2).
- Parse /etc/passwd with while readmedium · in-browser
Write /home/player/passwd-users.sh (shebang #!/bin/bash) that loops over /etc/passwd with `while IFS=: read -r` to split each colon-delimited record into fields, prints the username and UID with `printf`, and feeds the file in by redirecting after `done` (done < /etc/passwd).
(Authored config, graded structurally — the engine isn't run here.)
- Parse a config valuemedium
/etc/app/app.conf has KEY=VALUE lines (and # comment lines). Write /home/player/getconf.sh so that `getconf.sh KEY` prints just that key's value, and exits non-zero if the key is absent.
- Parse options with getoptsmedium
Write /home/player/cli.sh that accepts -n NAME and -g GREETING and prints `GREETING, NAME!`. Defaults: GREETING=Hello, NAME=World (so no args -> `Hello, World!`).
- Primality testmedium
Write /home/player/prime.sh that prints yes if $1 is prime else no.
- Self-Cleaning Temp Directorymedium · in-browser
Write /home/player/work.sh (shebang #!/bin/bash) that creates a private temporary directory with `mktemp -d`, then installs a `trap ... EXIT` that removes it with `rm -rf` so the directory is always deleted when the script ends, even on error.
(Authored config, graded structurally — the engine isn't run here.)
- Slurp a File with mapfilemedium · in-browser
Write /home/player/loadlines.sh (shebang #!/bin/bash) that reads all lines of the file named in $1 into an array using `mapfile -t` (stripping trailing newlines), then prints how many lines were read using ${#arr[@]}.
(Authored config, graded structurally — the engine isn't run here.)
- Sum a CSV columnmedium
/opt/data/sales.csv has a header then rows item,amount. Write /home/player/total.sh that prints the integer sum of the amount column.
- Sum a table columnmedium
Write /home/player/colsum.sh N FILE printing the integer sum of whitespace column N of FILE.
- Trim whitespacemedium
Write /home/player/trim.sh that prints $1 with leading/trailing whitespace removed (inner spaces kept).
- Unique lines, keep ordermedium
Write /home/player/uq.sh FILE printing FILE's lines de-duplicated preserving first-seen order.
- Cleanup with trappro
Write /home/player/work.sh that makes a temp file, prints its path, and removes it on EXIT via trap (so it is gone after the script ends).
- Interactive Menu with selectpro · in-browser
Write /home/player/menu.sh (shebang #!/bin/bash) that presents an interactive numbered menu using `select`. Set the menu prompt by assigning PS3, loop with `select VAR in start stop quit`, dispatch the chosen option with a `case`, and `break` out of the loop when the user picks the quit option.
(Authored config, graded structurally — the engine isn't run here.)
- Join two CSVs on a keypro
Write /home/player/join.sh A B. A has header `id,name`, B has header `id,score`. Print `id,name,score` (with that header) joining rows on id, sorted ascending by numeric id. Every id in A also appears in B.
- Most common wordpro
Write /home/player/mc.sh FILE printing the single most frequent whitespace word in FILE.
- Options with getopts and shiftpro · in-browser
Write /home/player/deploy.sh (shebang #!/bin/bash) that parses options with `while getopts`. Support a `-v` verbose flag and a `-f FILE` option (captured via OPTARG inside a case branch like `f)`), then drop the consumed options with `shift $((OPTIND-1))` so positional arguments remain in $@.
(Authored config, graded structurally — the engine isn't run here.)
- Read JSON without jqpro
There is no jq on this box. Write /home/player/jget.sh FILE KEY that prints the value of the top-level KEY in the JSON object in FILE (a string or number, printed raw with no quotes).
- Retry until successpro
Write /home/player/retry.sh N CMD... that runs CMD up to N times until it exits 0; exit 0 if any succeeds else non-zero.
- Slugify textpro
Write /home/player/slug.sh that turns $1 into a slug: lowercase, non-alphanumerced runs to single '-', trimmed (e.g. 'Hello, World!' -> hello-world).
- Tally with an Associative Arraypro · in-browser
Write /home/player/tally.sh (shebang #!/bin/bash) that counts occurrences of words read from stdin using an associative array. Declare it with `declare -A`, increment a keyed counter with (( arr[key]++ )), and finally iterate the keys with ${!arr[@]} to print each word and its count.
(Authored config, graded structurally — the engine isn't run here.)
- Validate user inputpro
Write /home/player/age.sh that, given $1, prints `valid` and exits 0 if $1 is a positive integer (no sign, no decimals), otherwise prints `invalid` and exits non-zero.
- Write a log rotatorpro
Write /home/player/rotate.sh <logfile> that rotates a log: <log>.2 -> <log>.3, <log>.1 -> <log>.2, <log> -> <log>.1, then truncates <log> to empty. Keep at most .1 .2 .3 (no .4).