Wildcards, aliases & shortcuts
Globbing, tab-completion, history, chaining.
Typing every filename by hand is like addressing a hundred envelopes one at a time when a single rubber stamp would cover them all. The shell (the program that reads what you type and turns it into running commands) gives you a handful of features that replace slow, careful typing with something faster and safer. None of them are hard. Each takes a minute to learn and then pays you back on every command you run for the rest of your career. For the security and operations work ahead, a few of them also change what you can see and what you can get badly wrong, so they carry real weight.
Wildcards: one pattern, many files
A wildcard is a stencil for filenames. Instead of naming each file, you describe the shape you want and let the shell fill in the rest. The formal name is globbing, after an old Unix helper program named glob (short for global) that did exactly this expansion. Three symbols do most of the work. An asterisk (*) matches any run of characters, including none of them. A question mark (?) matches exactly one character. Square brackets ([abc]) match any single character from the set inside them. So *.log means every name that ends in .log.
Here is the part that matters most. The shell expands the pattern before the command ever runs. Your command never sees the star. By the time rm or ls starts, the * has already been replaced with the real list of matching names. That is why the same pattern can be a big time-saver and a foot-gun in the same breath.
The other two symbols narrow things down. The question mark holds a spot for one character, and the brackets let you spell out a small set of allowed characters.
You can see exactly what a pattern will become before you act on it. Ask the shell to echo it. echo prints its arguments after expansion, so it shows you the literal list the next command would receive. Get in the habit of running this against any wildcard you are about to hand to something destructive.
One quiet rule both saves you and bites you: a plain * does not match names that begin with a dot. Files like .env (a common place to keep secrets such as database passwords) and .ssh (the directory that holds your login keys) stay invisible to it. That means cp * backup/ will not sweep up your secrets, which is good. It also means a cleanup script that trusts * can leave sensitive files sitting behind, or miss them entirely in an audit, which is worth carrying in your head.
Tab completion: let the shell finish your sentence
Tab completion is the shell's version of the contact list on your phone that fills in a name after you type two letters. Start a command or a path, press the Tab key, and the shell finishes it. If only one thing matches, it fills it straight in. If several match, press Tab twice and it lists your options.
It saves keystrokes, and it also does something quieter that matters more. The shell only completes paths and names that actually exist, so a line it finishes for you is a line you have verified. If you type the start of a directory and Tab fills in nothing, that directory is not there, and you have caught the mistake before pressing Enter on something you cannot take back. On a production server, that half-second of feedback is cheap insurance.
History and reverse search
The shell keeps a logbook of what you have run, like the redial list on a phone. The up-arrow walks back through recent commands one at a time. Better, Ctrl-R (hold the Control key and press R) starts a reverse search: type a few letters from any past command and it jumps to the most recent match, so a long command you ran last Tuesday comes back in six keystrokes.
That logbook is written to a file, ~/.bash_history (a hidden file of past commands in your home directory), and it is one of the first places both attackers and investigators look. If you ever type a password or an API key (a secret string that authenticates you to a service) directly on the command line, it lands there in plain text, readable by anyone who later gets into that account.
There is the leak, sitting in a file that survives every reboot. Two defenses. Put a space in front of any sensitive command, and with HISTCONTROL set to ignorespace (a setting that tells Bash to skip lines that begin with a space) it never reaches the history file. The deeper fix is to stop passing secrets as arguments at all. While a command runs, anyone else on the machine can read its full command line, arguments included, with ps aux (the command that lists every running process). A password in curl -u user:pass or mysql -pSecret is exposed the moment you press Enter, history file or not. Prefer a prompt, a config file with tight permissions, or an environment variable.
Chaining commands with ; && and ||
You can put several commands on one line, and the symbol between them decides how they relate, the way a recipe says bake the cake, and only if it rises, add the frosting. Every command reports a hidden number when it finishes: 0 means success, anything else means failure. You can read the last one with echo $? (the exit status of the previous command). The three connectors work off that number.
A semicolon (;) runs the commands in order no matter what happened. Two ampersands (&&) run the next command only if the previous one succeeded. Two pipes (||) run the next command only if the previous one failed. So build && deploy ships your code only when the build worked, and a failed step stops the line cold before it can do any harm.
The pull reported success, so the restart ran (systemd, the service manager on most modern Linux, stays quiet when a restart works). Flip the logic around and || gives you a plain-language alarm that only fires on failure.
A semicolon, by contrast, plows ahead even when the first part fails, and that is where it turns into a trap. The line below is a classic way to wreck a machine: the cd fails, the semicolon shrugs, and the delete runs wherever you happened to be standing instead of in the directory you meant.
Written with && instead of ;, the failed cd would have stopped the whole line and nothing would have been deleted. The rule that follows from this: in scripts, chain steps that depend on each other with &&, not with a semicolon. A step should never run on the assumption that the one before it worked.
Aliases: nickname your common commands
An alias is a nickname (a speed-dial button) for a longer command. You define it once, and from then on the short name stands in for the full thing. Type the nickname, the shell swaps in the real command, and runs it. To make aliases stick around after you close the terminal, put them in ~/.bashrc (a startup file that Bash reads every time it opens a new interactive shell).
alias ll='ls -alF' # long listing, all files, with type markersalias gs='git status'alias ..='cd ..'alias rm='rm -i' # ask before deleting each file# apply changes to the current shell with: source ~/.bashrc
The rm -i alias is a small safety net that makes every delete ask first. Aliases are also how you catch trouble. You can always ask what a name really points to with the type command, and you can force the real command past an alias by putting a backslash in front of it.
That backslash trick cuts both ways, and it is why ~/.bashrc deserves a security engineer's attention. Anyone who can write to your dotfiles can plant an alias that quietly replaces a command you trust. An alias named sudo pointed at a fake password prompt, or an ls that also copies files out to a stranger, runs every time you use the real name and survives every reboot. It is a favorite way for an intruder to stay on a machine after a break-in, what defenders call persistence. When a box feels off, read ~/.bashrc, ~/.bash_profile, and the files under /etc/profile.d/, and run type on the commands you lean on. Most systems ship a harmless alias or two (ls is usually set to add color), so what you are hunting for is anything you did not put there: an alias, function, or script standing in front of a command you assumed was the real binary.
One habit to build starting today: before any rm, cp, or mv that uses a wildcard, run the same pattern through ls or echo and read the result back. It costs two seconds, and it is the whole difference between deleting three log files and deleting three hundred.
Try this
Work through “Aliases: nickname your common commands” yourself on a sandbox you can throw away, following the commands above in order. Then break one step deliberately and re-run, so you have seen the failure before it finds you.
Takeaway
The trap worth remembering here: a wildcard is resolved before your command sees it. Check that on your own systems before you need to, because it is cheaper to find on a quiet afternoon than during an incident.