In the previous lesson you completed your mental model of the shell: you know what happens when you press Enter, how commands are resolved and why variables do not survive a subshell. One cross-cutting skill remains before entering the command arsenal of Module 2, and it is probably the most profitable of the whole course: being able to answer your own questions. No professional remembers the forty options of find, the order of the fields in a crontab or the differences between -exec and xargs. What they do know is where to look it up in ten seconds and how to verify a dangerous command before firing it at srv-veloz-01. That is what you will learn here.

Contents

  1. The documentation ecosystem in Linux
  2. man: the system manual
  3. The manual sections
  4. Navigating and searching inside a manual page
  5. Reading a SYNOPSIS: the formal notation
  6. Searching when you do not know the command's name: man -k and apropos
  7. help: the Bash builtins and why man cd fails
  8. --help: quick help
  9. info, tldr and cheat
  10. Official documentation: the Bash manual and POSIX
  11. A practical strategy for answering questions
  12. Verifying dangerous commands before running them

  1. The documentation ecosystem in Linux

Linux is probably the best documented system in existence, but the documentation is spread across several sources with different purposes. Knowing which one to consult at any moment saves an enormous amount of time.

Source How it is invoked Covers Depth When to use it
man man ls External programs, file formats, system calls High, exhaustive A complete and reliable reference
help help cd Bash builtins Medium cd, export, test, read...
--help ls --help The program itself Low, a summary Recalling an option quickly
info info coreutils Extensive GNU manuals Very high When man refers you to info
tldr tldr tar Real usage examples Very low "How did you do this again?"
Bash manual Web or man bash The complete Bash language Maximum Shell syntax questions
POSIX Web The standard Maximum Portability

The mental rule you should internalise is simple:

  • If it is a program (ls, grep, tar, find) → man.
  • If it is a Bash builtin (cd, export, read, test) → help.
  • If it is shell syntax ([[ ]], expansions, redirections) → man bash.
  • If you just want an exampletldr.

  1. man: the system manual

man (from manual) is the canonical reference. Every installed program ships its page, written by its author.

man ls

It opens a document with a standardized structure that you will see over and over:

Section Contents
NAME Name and a one-line description
SYNOPSIS The invocation form with its formal syntax
DESCRIPTION Detailed explanation and list of options
OPTIONS The options, if they are not in DESCRIPTION
EXIT STATUS Exit codes and their meaning
ENVIRONMENT Environment variables that affect the program
FILES Files it uses or reads
EXAMPLES Usage examples (not every page has them)
SEE ALSO Related commands
BUGS Known limitations

A real extract from man ls:

NAME
       ls - list directory contents

SYNOPSIS
       ls [OPTION]... [FILE]...

DESCRIPTION
       List information about the FILEs (the current directory by default).
       Sort entries alphabetically if none of -cftuvSUX nor --sort is
       specified.

       -a, --all
              do not ignore entries starting with .

       -h, --human-readable
              with -l and/or -s, print human readable sizes (e.g., 1K 234M 2G)

       -t     sort by time, newest first

Notice two things that come up constantly:

  • Options with a short and a long form are listed together: -a, --all.
  • There are dependencies between options: -h explicitly says "with -l and/or -s". In other words, ls -h on its own does nothing visible. This kind of nuance only appears in the manual, never in a hurried tutorial.

And the EXIT STATUS section of man ls confirms what we saw in 01-04:

EXIT STATUS
       0      if OK,
       1      if minor problems (e.g., cannot access subdirectory),
       2      if serious trouble (e.g., cannot access command-line
              argument).

  1. The manual sections

The manual is divided into numbered sections. This matters because the same name can appear in several of them.

Section Contents Example
1 User commands man 1 crontab → the crontab program
2 System calls (kernel) man 2 fork
3 C library functions man 3 printf
4 Special files in /dev man 4 null
5 File formats and conventions man 5 crontab → the file format
6 Games man 6 fortune
7 Miscellany, conventions, protocols man 7 regex, man 7 signal
8 Administration commands man 8 mount, man 8 cron

The three you will really use are 1 (commands), 5 (file formats) and 8 (administration).

The canonical example of why this matters is crontab, which we will use in Module 7:

man 1 crontab
CRONTAB(1)                    User Commands
NAME
       crontab - maintain crontab files for individual users
SYNOPSIS
       crontab [-u user] file
       crontab [-u user] [-l | -r | -e]
man 5 crontab
CRONTAB(5)                File Formats
NAME
       crontab - files used to schedule the execution of programs

DESCRIPTION
       ...
       field          allowed values
       -----          --------------
       minute         0-59
       hour           0-23
       day of month   1-31
       month          1-12 (or names)
       day of week    0-7 (0 or 7 is Sunday, or use names)

Section 1 tells you how the program is invoked; section 5 tells you how the file is written. If you type a plain man crontab, you get section 1, which does not contain the field table. A great many people get stuck here and end up searching the internet for something that was one command away.

To find out which sections a name exists in:

man -f crontab
crontab (1)          - maintain crontab files for individual users
crontab (5)          - files used to schedule the execution of programs

And to open all of them directly, one after another:

man -a crontab

  1. Navigating and searching inside a manual page

man does not dump the text at you: it passes it to a pager, usually less. That is why man's shortcuts are really less's shortcuts, and they will serve you just as well when reading long logs.

Key Action
Space / f Forward one screen
b Back one screen
/ j Down one line
/ k Up one line
g Go to the beginning
G Go to the end
/text Search forwards
?text Search backwards
n Next match
N Previous match
q Quit
h The pager's own help

Searching with / is the most important technique in this lesson. A manual page like find's has more than a thousand lines; reading it end to end is absurd. What you do is search.

A real example: you want to know how to make ls sort by size.

man ls

Once inside, type /sort and press Enter. Press n until you reach:

       -S     sort by file size, largest first

Another, even more useful example, looking for a specific option. To locate the exact description of -t in man ls, the search /^\s*-t takes advantage of the fact that options are indented at the start of a line. Regular expressions are studied in 05-04, but from today you can use the trick of searching for -t, or straight for --sort.

A configuration tip: if you prefer searches to ignore case, export this in your ~/.bashrc:

export LESS='-R -i'

-R preserves colors and -i makes searches case-insensitive unless you type a capital letter.

  1. Reading a SYNOPSIS: the formal notation

The SYNOPSIS is the densest part and the one most people ignore, when in reality it condenses the whole grammar of the command. It uses a standard notation:

Notation Meaning Example
text in bold Type it exactly ls
TEXT in italics/capitals Replace it with your value FILE
[ ] Optional [OPTION]
... Can be repeated [FILE]...
| Alternative: pick one [-l | -r | -e]
{ } A group of mandatory alternatives {-a | -b}

Let us analyze real cases.

ls [OPTION]... [FILE]...

It reads: ls accepts zero or more options and zero or more files. Both are optional, which is why a bare ls works.

cp [OPTION]... SOURCE... DIRECTORY

It reads: cp accepts options (optional), one or more sources (mandatory, no brackets) and one destination directory (mandatory, no ellipsis). The structure tells you at a glance that the last argument is the destination and that there can be several sources.

crontab [-u user] [-l | -r | -e]

It reads: optionally -u with a user name, and optionally just one of the three options -l, -r, -e. The vertical bar warns that they are mutually exclusive: crontab -l -e makes no sense.

grep [OPTIONS] PATTERNS [FILE...]

It reads: the pattern is mandatory; the files are optional and there can be several. The fact that FILE is optional is the clue that, if you do not supply one, grep will read from standard input, which is exactly what lets you use it in pipelines.

Learning to read the SYNOPSIS lets you deduce a command's behavior without reading a single line of the description.

  1. Searching when you do not know the command's name: man -k and apropos

The most frequent problem is not "how do I use this command?", but "which command does this?". That is what keyword search across the descriptions is for.

man -k compress
gzip (1)             - compress or expand files
bzip2 (1)            - a block-sorting file compressor
xz (1)               - Compress or decompress .xz files
zcat (1)             - decompress files to stdout

apropos is exactly the same thing:

apropos "disk space"
df (1)               - report file system disk space usage
du (1)               - estimate file space usage

You can narrow the search to a section:

man -k -s 1 "log"

And combine it with grep to filter further:

man -k file | grep -i "permission"
chmod (1)            - change file mode bits
chown (1)            - change file owner and group

If man -k returns nothing appropriate, the index database has probably not been built. It is fixed with:

sudo mandb

  1. help: the Bash builtins and why man cd fails

Let us pick up something from lesson 01-04. Try this:

man cd
No manual entry for cd

You already know the explanation: cd is not a program, it is a Bash builtin. There is no /usr/bin/cd file that could ship its own manual page. The documentation for builtins lives inside Bash itself, and you consult it with help:

help cd
cd: cd [-L|[-P [-e]] [-@]] [dir]
    Change the shell working directory.

    Change the current directory to DIR.  The default DIR is the value of
    the HOME shell variable.

    Options:
      -L	force symbolic links to be followed: resolve symbolic
    		links in DIR after processing instances of `..'
      -P	use the physical directory structure without following
    		symbolic links: resolve symbolic links in DIR before
    		processing instances of `..'

    Exit Status:
    Returns 0 if the directory is changed, and if $PWD is set successfully
    when -P is used; non-zero otherwise.

A quick check of the rule, leaning on type (01-04):

type -a cd export ls
cd is a shell builtin        ← help cd
export is a shell builtin    ← help export
ls is /usr/bin/ls            ← man ls

If type says "is a shell builtin", use help. If it gives you a path, use man.

Builtins whose help you will consult often during this course:

help test        # comparisons with [ ... ]
help read        # reading user input (03-05)
help declare     # variable types and arrays (04-03)
help printf      # formatted output
help set         # shell options: set -e, set -u...
help trap        # trapping signals (05-03)

With no arguments, help lists every available builtin:

help

And it accepts patterns:

help 'ex*'
exec: exec [-cl] [-a name] [command [arguments ...]] [redirection ...]
exit: exit [n]
export: export [-fn] [name[=value] ...] or export -p

There is a special case worth knowing about. Some builtins also exist as an external program, so they have both sets of documentation:

type -a test
test is a shell builtin
test is /usr/bin/test

help test documents the builtin that actually runs; man test documents the coreutils program. They are almost identical, but not quite. The right one is help test, because it is the one Bash uses. The same happens with echo, printf, kill and pwd.

Finally, for the syntax of the language itself (not a builtin, but constructs such as [[ ]], ${var%%pattern} or redirections), the source is the Bash manual page:

man bash

It is enormous (over 5,000 lines), so you navigate it by searching. For example, type /Conditional Expressions to reach the documentation for [[ ]], or /Parameter Expansion for ${...}. It is the definitive shell reference and you will come back to it throughout the course.

  1. --help: quick help

Almost every program accepts --help and prints a summary on screen.

date --help
Usage: date [OPTION]... [+FORMAT]
  or:  date [-u|--utc|--universal] [MMDDhhmm[[CC]YY][.ss]]
Display the current time in the given FORMAT, or set the system date.

  -d, --date=STRING          display time described by STRING, not 'now'
  -f, --file=DATEFILE        like --date; once for each line of DATEFILE
  -r, --reference=FILE       display the last modification time of FILE
  -u, --utc, --universal     print or set Coordinated Universal Time (UTC)

FORMAT sequences:
  %Y   year
  %m   month (01..12)
  %d   day of month (01..31)
  %H   hour (00..23)

Advantages over man: it is instantaneous, it does not open a pager and it usually fits on one screen. It is what you will use 80% of the time to recall a specific option.

Important warnings:

  • It is not universal. Some programs use -h, others -?, and a few neither. If --help does not work, try -h and then man.
  • Beware of commands that interpret --help as an argument. A famous case: in find, --help does work, but in older programs an unknown argument can produce odd behavior.
  • If the output is long, pipe it to a pager:
find --help | less

A very practical trick when you are after a specific option: filter the help with grep.

ls --help | grep -i "size"
  -h, --human-readable       with -l and -s, print human readable sizes
      --block-size=SIZE      with -l, scale sizes by SIZE when printing them
  -S                         sort by file size, largest first
      --size, -s             print the allocated size of each file, in blocks

In four lines you have every size-related option. This command --help | grep combination is a reflex you will pick up fast.

  1. info, tldr and cheat

9.1 info

The GNU project documents its tools with info, a format with hyperlinks and a tree structure. Many GNU man pages are really summaries and end with a note along the lines of "the full documentation is in the info manual".

info coreutils 'ls invocation'

Basic navigation:

Key Action
Space Forward
n / p Next / previous node
u Up one level
Enter on a link Follow it
q Quit

info is more complete than man for coreutils (it contains examples and lengthy explanations), but its navigation feels awkward if you are not used to it. Turn to it when man leaves you with doubts.

9.2 tldr

tldr (too long; didn't read) is a community project that offers practical examples only. It is the perfect complement to man: the latter tells you what each option does, the former tells you how it is actually used.

sudo apt install tldr    # Debian/Ubuntu
tldr tar
tar

Archiving utility, often combined with compression.

- Create a compressed archive:
  tar czf path/to/archive.tar.gz path/to/files

- Extract a compressed archive:
  tar xzf path/to/archive.tar.gz

- List the contents without extracting:
  tar tvf path/to/archive.tar

Compare: man tar has more than 1,200 lines; tldr tar fits in half a screen and solves 90% of the cases. For commands with intricate syntax (tar, find, ffmpeg, awk) it is a blessing.

9.3 cheat

cheat is similar but lets you create your own cheat sheets, which fits very well with a toolkit like veloz-ops:

cheat -e veloz-ops

Your editor opens and you can save your own notes, which you then consult with cheat veloz-ops. It is an excellent way of documenting internal team conventions.

A warning about tldr and cheat: they are community content, not official. They are great for jogging your memory, but when something is critical or the behavior does not match, the truth is in man.

  1. Official documentation: the Bash manual and POSIX

There are two written references that every Bash professional should know.

10.1 The Bash Reference Manual

This is the official GNU project document, maintained by Chet Ramey. It covers the complete language: grammar, expansions, builtins, job control, line editing. It is available on the GNU website and, locally, with:

info bash
man bash

It is the source that settles any argument about Bash's behavior. When in Module 3 we ask ourselves exactly in what order expansions happen, the answer is in its EXPANSION section.

10.2 The POSIX standard

POSIX (Portable Operating System Interface) is the standard that defines the minimum common behavior of Unix shells. It is published by The Open Group and it is the reference for writing portable scripts.

Its practical use is answering the question: "is this thing I am using Bash-specific or standard?". If it is Bash-only, your script will not work in dash, on Alpine or on a BSD. The Bash documentation marks its own extensions, and in lesson 08-07 we will work on portability in detail.

10.3 ShellCheck (a mention)

ShellCheck is a static analyzer that finds errors in shell scripts before you run them: unquoted variables, badly written comparisons, usages that lead to unexpected behavior. Every warning carries an SCxxxx code (for example, SC2086 for "double quote to prevent globbing and word splitting"), and the project wiki explains each one with examples of what breaks and how to fix it.

We mention it here because it is documentation: the ShellCheck wiki is one of the best sources for understanding the classic Bash mistakes. Its installation and use are covered in lesson 08-05; for now, just remember the name.

  1. A practical strategy for answering questions

With so many sources, it helps to have a procedure. This is the one that works.

graph TD
    A["I have a question"] --> B{"Do I know the<br/>command's name?"}
    B -->|No| C["man -k keyword<br/>apropos"]
    C --> D
    B -->|Yes| D{"type -a command"}
    D -->|"Shell builtin"| E["help command"]
    D -->|"Path to a file"| F{"Do I need one option<br/>or the full detail?"}
    F -->|"Just one option"| G["command --help filtered with grep"]
    F -->|"Detail"| H["man command<br/>+ / to search"]
    D -->|"It is shell syntax"| I["man bash + /section"]
    E --> J{"Solved?"}
    G --> J
    H --> J
    I --> J
    J -->|No| K["tldr command<br/>info command<br/>official manual"]
    J -->|Yes| L["Verify before running"]
    K --> L

Translated into concrete steps:

  1. Do I know the name? If not, man -k with a keyword describing what you want (the descriptions are indexed as a single line per command).
  2. type -a command to find out whether it is a builtin, external or a keyword. This decides the source.
  3. Quick help first: command --help | grep whatImLookingFor. It answers most queries in seconds.
  4. If you need detail, man command and search inside with /. Do not read top to bottom.
  5. If it is still unclear, tldr command for real examples, or info for the GNU tools.
  6. Verify before running (next section). This step is not optional on a production server.

One method tip that makes a difference: when you learn something by consulting the manual, write it down. A ~/veloz-ops/etc/notes.md file with the options you have needed turns every search into accumulated knowledge rather than a repeated lookup.

  1. Verifying dangerous commands before running them

This section can save you from a serious incident. srv-veloz-01 holds production data; a misunderstood command can delete a month's worth of shipments.

12.1 Putting echo in front

The simplest and most effective technique: prefix echo and look at what would actually have run. Remember from lesson 01-04 that expansions happen before the command runs, so echo shows you the exact result of those expansions.

cd /var/log/veloz
echo rm access.log.*
rm access.log.1 access.log.2 access.log.3

Now you can see precisely which files would be affected. If the list is the one you expected, drop the echo and run it. If something unexpected shows up, you have just avoided a problem.

The case where this really saves you:

echo rm -rf /srv/veloz/data /archive
rm -rf /srv/veloz/data /archive

The accidental space before /archive turns one path into two independent arguments. With echo you see it; without echo, you would have deleted two different trees.

12.2 Using --dry-run where it exists

Many commands offer a simulation mode:

Command Simulation option
rsync -n, --dry-run
apt --dry-run, -s
make -n, --just-print
git clean -n
find ... -delete Remove -delete and look at the list first
sed -i Run it without -i and look at the output
rsync -avn /srv/veloz/data/ /mnt/backup/data/

The n of --dry-run makes rsync list exactly what it would copy, without copying anything. In lesson 07-03, when we build the veloz-ops backup system, this will be the mandatory first step of every test.

How to find out whether a command has a simulation mode:

rsync --help | grep -i "dry"
 -n, --dry-run               perform a trial run with no changes made

12.3 Other precautions

  • Run the read-only part first. Before find /srv -name "*.tmp" -delete, run find /srv -name "*.tmp" and review the list.
  • Use -i (interactive) on destructive commands. rm -i asks about each file.
  • Check where you are and who you are. pwd and whoami before any deletion. An rm -rf * in the wrong directory is irreversible.
  • Distrust commands copied from the internet, especially those carrying sudo, curl | bash, rm -rf or absolute system paths. Read them in full, break them down and look up in man every option you do not recognize.
  • In Linux there is no recycle bin. rm cannot be undone.

An exercise in critical reading. Someone passes you this line "to clean up old logs":

find /var/log -name "*.log" -mtime +7 -exec rm -f {} \;

Before running it, you break it down by consulting man find:

  • -name "*.log": files ending in .log.
  • -mtime +7: modified more than 7 days ago. (Searching for /mtime in the manual you discover that +7 means "more than 7 full days", a nuance that is often misread.)
  • -exec rm -f {} \;: runs rm -f on each result.

And you spot the problem: it acts on all of /var/log, not just on /var/log/veloz. It would also delete the system and nginx logs. The safe version would be:

# First look, without deleting anything
find /var/log/veloz -name "*.log.*" -mtime +7

# Only if the list is correct
find /var/log/veloz -name "*.log.*" -mtime +7 -delete

That habit — break it down, look it up, list it, and only then run it — is what separates a professional from someone who one day has a very bad day.

Common Mistakes and Tips

  • Searching for man cd and concluding the documentation does not exist. It is a builtin: help cd. Always check with type -a first.
  • Typing man crontab and not finding the file format. You need section 5: man 5 crontab. Use man -f name to see which sections it exists in.
  • Reading a manual page from top to bottom. They are reference documents, not tutorials. Go in and search with /.
  • Trusting tldr for something critical. It is community content and it can be out of date. For important decisions, man.
  • Ignoring the SEE ALSO section. It often contains exactly the command you needed and did not know existed.
  • Not reading EXIT STATUS. If you are going to use a command inside a script, its exit codes matter as much as its options.
  • Running destructive commands without verifying. echo in front, or --dry-run. Always, even when you think it is obvious.
  • Tip: if man -k returns nothing, run sudo mandb to rebuild the index.
  • Tip: man man and man bash deserve one unhurried read at least once in your life. Not to memorise them, but to know what they contain.
  • Tip: manual pages use a terse, consistent house vocabulary (pattern, recursive, verbose, overwrite, suppress). Once you recognize the style, pages you have never opened become readable at a glance.

Exercises

Exercise 1: Finding real options in man ls and man grep

Using the manual pages exclusively (no web searches), find out:

  1. Which ls option shows each file's inode number.
  2. Which ls option sorts by modification date from oldest to newest (you need to combine two).
  3. Which grep option shows the 3 lines following each match.
  4. Which grep option shows only the name of the files containing the match, without the lines.
  5. Which grep option inverts the search, showing the lines that do not match.

Then apply what you have learned to a Veloz Envíos case: list the files in /var/log/veloz from oldest to newest, and locate every ERROR in app.log with its 3 lines of following context.

Exercise 2: help test and the builtins

  1. Check with type -a whether test is a builtin, external or both.
  2. With help test, find out what the -f, -d, -r, -s and -z operators do.
  3. Also find out how to check whether one file is newer than another.
  4. Write a one-line command that prints "exists" if /var/log/veloz/app.log exists and has content.

Exercise 3: Verifying a dangerous command

A colleague sends you this command "to free up space on the server":

find /srv/veloz -type f -name "*.csv" -mtime +30 -exec rm -f {} \;
  1. Break it down by consulting man find, explaining each part.
  2. Find out exactly what +30 means in -mtime (look it up in the manual, do not assume).
  3. Identify at least two risks of running it as it stands at Veloz Envíos.
  4. Propose a verifiable and safer version.

Solutions

Solution to Exercise 1

Procedure: man ls, then /inode, /sort, and so on. A quicker alternative: ls --help | grep -i inode.

  1. -i, --inode: prints each file's index number.
  2. -t combined with -r: -t sorts by date with the newest first, and -r reverses the order. Hence ls -ltr. It is one of the most used combinations in systems administration: it leaves the most recent entry right at the bottom, just above the prompt, which is where you are looking.
  3. -A NUM, --after-context=NUM: shows NUM following lines. With -B you get the preceding ones and with -C both.
  4. -l, --files-with-matches: only the names of the files with a match.
  5. -v, --invert-match: selects the lines that do not match.

Applied to Veloz Envíos:

ls -ltr /var/log/veloz
total 47M
-rw-r--r-- 1 veloz    veloz 2.1M Aug  2 23:59 app.log.1
-rw-r--r-- 1 www-data adm   9.4M Aug  2 23:59 access.log.1
-rw-r--r-- 1 veloz    veloz 1.3M Aug  3 09:02 veloz-api.log
-rw-r--r-- 1 www-data adm    28M Aug  3 10:14 access.log
-rw-r--r-- 1 veloz    veloz 6.0M Aug  3 10:15 app.log
grep -A 3 'ERROR' /var/log/veloz/app.log | head -20
2026-08-03 10:12:04 [ERROR] Timeout connecting to payment gateway (shipment E-4471)
2026-08-03 10:12:05 [INFO] Retry 1 of 3 for shipment E-4471
2026-08-03 10:12:09 [INFO] Retry 2 of 3 for shipment E-4471
2026-08-03 10:12:14 [WARN] Retries exhausted, marking E-4471 as issue
--
2026-08-03 10:14:31 [ERROR] Could not write to /srv/veloz/data/shipments.csv

The following context is exactly what you need to understand an error: the ERROR line says what failed, and the next ones say how the application reacted. The -- separators mark non-contiguous blocks.

Solution to Exercise 2

type -a test
test is a shell builtin
test is /usr/bin/test
  1. It is both: it exists as a Bash builtin and as a coreutils program. Bash uses the builtin (builtins take priority over the PATH, as we saw in 01-04), so the relevant documentation is help test.

  2. Consulting help test:

Operator True if...
-f FILE It exists and is a regular file
-d FILE It exists and is a directory
-r FILE It exists and you have read permission
-s FILE It exists and its size is greater than zero
-z STRING The string has zero length
  1. FILE1 -nt FILE2 (newer than): true if FILE1 is more recent, by modification date, than FILE2. There is also -ot (older than) and -ef (same device and inode). This operator will be very useful in Module 7 to know whether a backup is up to date.

  2. -s FILE applied to our application log:

test -s /var/log/veloz/app.log && echo "exists"
exists

-s is more appropriate than -f here, because it checks at once that it exists and that it is not empty. The && operator runs the second part only if the first returned code 0; it is a direct application of the exit codes from lesson 01-04 and it is formalised in 03-03. Written with the modern syntax it would be:

[[ -s /var/log/veloz/app.log ]] && echo "exists"

Solution to Exercise 3

  1. Breakdown (consulting man find):
Part Meaning
/srv/veloz The directory where the search starts, recursive by default
-type f Regular files only (no directories or links)
-name "*.csv" Whose name ends in .csv
-mtime +30 Modified more than 30 days ago
-exec rm -f {} \; Runs rm -f on each result; {} is replaced by the name and \; closes the -exec
  1. What +30 means. Searching for /mtime in man find you find:
       -mtime n
              File's data was last modified n*24 hours ago.  When find
              figures out how many 24-hour periods ago the file was last
              modified, any fractional part is ignored...

And in the earlier section on numeric arguments:

       +n     for greater than n,
       -n     for less than n,
       n      for exactly n.

So +30 means modified more than 30 complete 24-hour periods ago. The important nuance is that the fractional part is discarded: a file that is 30 days and 20 hours old counts as 30, not 31, and would not be selected. This behavior surprises a lot of people and it is only written down in the manual.

  1. Risks:

    • Excessive scope: it acts on all of /srv/veloz recursively, including the archive subdirectory, which is precisely where old files are kept on purpose. It would delete the shipment history.
    • Irreversibility with no verification: rm -f does not ask and leaves no trace, and in Linux there is no recycle bin. If the criterion is wrong, the data is gone.
    • Additional risk: -exec ... \; launches one rm process per file, which with thousands of files is very slow and can saturate the server. The efficient form is -exec rm -f {} + or -delete.
    • Risk with odd names: if some file had a name with special characters, certain variants of this pattern break. -delete avoids that.
  2. A safe, verifiable version:

# Step 1: see exactly what would be selected, narrowing the scope
find /srv/veloz/data -maxdepth 1 -type f -name "shipments-*.csv" -mtime +30

# Step 2: review the list in detail (size and date)
find /srv/veloz/data -maxdepth 1 -type f -name "shipments-*.csv" -mtime +30 -ls

# Step 3: if and only if the list is correct, delete
find /srv/veloz/data -maxdepth 1 -type f -name "shipments-*.csv" -mtime +30 -delete

Improvements applied:

  • -maxdepth 1 stops it from descending into archive.
  • The shipments-*.csv pattern is more specific and does not touch the active shipments.csv.
  • It is run first with no destructive action so the list can be reviewed.
  • -delete replaces -exec rm, and it is faster and safer.

The definitive version for veloz-ops would also move files to a quarantine directory instead of deleting them, but that will come in lesson 07-03.

Conclusion

With this lesson you close Module 1 and, with it, the foundations of the course. You now know what Bash is and what role it plays in your work; you have a modern environment set up with ~/veloz-ops in the PATH; you move around the srv-veloz-01 filesystem with judgement; you understand what happens under the hood when you press Enter; and now, on top of that, you are self-sufficient at answering your own questions: you know when to use man and when help, how to pick the right section, how to search inside a page with /, how to decipher a SYNOPSIS, how to find a command you do not know with man -k, and — the most important thing on a production server — how to verify a dangerous command before running it.

That last point is the one that will save you most often. All the power you are about to acquire in the coming modules is also power to destroy, and the difference lies in the habit of checking before acting.

In Module 2 the real work with the tools begins: you will learn to create, copy, move and delete files; to process text with cat, head, tail, grep, sort and wc; to understand and change permissions; to chain commands with redirections and pipelines; to use wildcards; and to move around the command line at professional speed. From there on, everything you learn will go straight into building veloz-ops.

Bash Programming Course

Module 1: Introduction to Bash

Module 2: Basic Bash Commands

Module 3: Scripting Fundamentals

Module 4: Intermediate Scripting

Module 5: Advanced Scripting Techniques

Module 6: Working with External Tools

Module 7: Automation and Scheduling

Module 8: Best Practices and Optimization

Module 9: Real-World Projects

© Copyright 2026. All rights reserved