October 14, 2026 - 20:48
Build a Bash Menu for Creating and Deleting Test Files Image
Server Management

Build a Bash Menu for Creating and Deleting Test Files

Comments

A menu script is a useful way to practice input, branching and loops in Bash. It is also an easy place to make a destructive mistake if a filename is treated as shell syntax or a path is allowed to escape the exercise folder.

This version creates its own private temporary directory and operates only on simple filenames inside it. Run it as an ordinary user, not with sudo. It is a learning exercise, not a general file manager or a security boundary against another process running as the same user.

The menu script

Save the code as menu.sh with Unix line endings and run bash menu.sh. Use Bash, not sh: the filename validation uses Bash conditional syntax.

BASH
#!/usr/bin/env bash
umask 077
workdir=$(mktemp -d) || exit 1
printf 'Exercise directory: %s\n' "$workdir"
trap 'printf "Files retained in: %s\n" "$workdir"' EXIT

while true; do
  printf '\n1. Create file\n2. Delete file\n3. Exit\nChoice: '
  IFS= read -r choice || break
  case "$choice" in
    1|2)
      printf 'Filename (letters, digits, spaces, dot, underscore, hyphen): '
      IFS= read -r name || break
      if [[ ! $name =~ ^[a-zA-Z0-9][a-zA-Z0-9._\ -]*$ ]]; then
        printf 'Invalid filename. Paths and leading punctuation are not allowed.\n'
        continue
      fi
      target="$workdir/$name"
      if [[ $choice == 1 ]]; then
        if [[ -e $target || -L $target ]]; then
          printf 'Already exists; nothing overwritten.\n'
        elif (set -o noclobber; : > "$target"); then
          printf 'Created: %s\n' "$name"
        else
          printf 'Creation failed.\n' >&2
        fi
      else
        if [[ ! -f $target || -L $target ]]; then
          printf 'Not an ordinary exercise file.\n'
          continue
        fi
        printf 'Delete "%s"? Type DELETE: ' "$name"
        IFS= read -r answer || break
        if [[ $answer != DELETE ]]; then
          printf 'Cancelled.\n'
        elif rm -- "$target"; then
          printf 'Deleted: %s\n' "$name"
        else
          printf 'Deletion failed.\n' >&2
        fi
      fi
      ;;
    3) break ;;
    *) printf 'Choose 1, 2 or 3.\n' ;;
  esac
done

Why the input handling is deliberate

IFS= read -r reads the line without trimming its whitespace or treating backslashes as escapes. The filename rule then deliberately accepts a smaller set of characters. A slash, an empty name, ../notes and a leading hyphen are rejected. A name such as draft 1.txt is accepted and stays one argument because every filesystem path is quoted.

The case statement chooses an action, while the loop displays the menu again after that action. End-of-input exits rather than spinning forever. The GNU Bash manual documents read, conditional expressions, quoting and case.

Creation and deletion need different safeguards

Creating an existing name must not truncate a file. The script checks for existing entries and uses a no-clobber redirection when creating the empty file. Deletion requires a regular file, rejects symbolic links and asks for the exact confirmation word. It never recursively removes directories.

Even with these checks, a shell script is not designed to defeat hostile concurrent manipulation by the same account. Keep this exercise separate from a shared upload directory or production data. Do not turn the temporary path into a user-supplied arbitrary directory without redesigning the constraints.

Exercise the failure paths too

Create draft 1.txt, try creating it again, cancel a deletion, then confirm the deletion. Try an invalid menu choice and an invalid path. Each response should tell you whether anything changed. The script intentionally keeps its temporary folder on exit and prints its location; inspect it and remove only that specific exercise folder when finished.

Related Articles

Comments ()

No comments yet. Be the first to comment!

Leave a Comment