All commands shown in this post are compatible with a Bash shell. I cannot guarantee compatibility with other types of shells

This post is aimed at users who know the basics of the command line but want to learn some of the lesser known fundamentals. I’ll describe several concepts and provide code examples to reinforce these concepts.

Wildcard matching

The shell provides special characters that we can use to help search for filenames.

(*) will match any number of characters

(?) will match any single character

[set of characters] will match any character within the set

[[:class-matcher:]] will match whatever the class specifies

For example:

steven$: echo D*
Desktop Documents Downloads

Matched all the files that start with a capital 'D' and then match any number of characters after from within my directory

steven$: echo D[oe]*
Desktop Documents Downloads

Matched all the files that start with 'D' and then have an 'o' or an 'e' then any number of characters after

steven$: echo [[:uppercase:]]*
Applications Desktop Documents Downloads Google Drive Library Movies Music Pictures

Here we match any files that start with an uppercase letter then match any number of characters after

You may want to link files or in other words have another filename that refers to the same file. There are two types of linking. Hard linking and symbolic linking.

Hard linking is kind of like making a copy of a file except changes in one are reflected in the other. It is indistinguishable from the file it’s linked to. If the original file is deleted the hard link remains.

To make a hardlink you use 'ln' [source file] [new linked file]:

$steven: ln my_file.txt my_file-hardlinked

Now a file named my_file-hardlinked is created.

Symbolic linking is a little bit different. They are the newer and preferred method of linking. A symbolic link is a pointer to the original source file. If you make a change in one it is reflected in the other. If you delete the source file the symbolic link will exist but will now be broken.

To make a symbolic link follow the same procedure as hard link but use a '-s' option:

$steven: ln -s my_file.txt my_file-symlinked 

Now a file name my_file-symlinked is created.

A symbolically linked file can be easily identified by an arrow pointing to the file if you run a command like:

$steven: ls -l my*
lrwxr-xr-x  1 steven  staff  11 Oct 11 15:37 my_file-symlinked -> my_file.txt


Expansions refers to the processing bash does before outputting results. Certain symbols or modifiers have a special meaning to Bash.

One basic example is the tilde (~). If I were to simply ehco '~':

steven$: echo ~

Bash would look at the tilde I gave it and expand it to it’s real meaning.

Another example is using wildcards which are really pathname expansions. For example from my home directory I can:

steven$: echo D*
Desktop Documents Downloads

Now for one of my favorite tricks we have what’s called brace expansion. The way this works is that you give a range within braces and the expansion essentially loops through the range.

For example:

steven$: echo File-{A..D}
File-A File-B File-C File-D

Now what’s a cool way to use this?

steven$: mkdir {2000..2003}-{A..C}
steven$: ls
2000-A 2000-B 2000-C 2001-A 2001-B 2001-C 2002-A 2002-B 2002-C 2003-A 2003-B 2003-C

The thing to note here is that when the two expansions aren’t space separated the second expansion runs like a nested loop.

Command Substitution

Command substitution means that we can use normal bash commands as expansions. This can be very useful. To carry out command substitutions just put your command in this format: $(command)

For example:

steven$: echo $(ls)
Applications Desktop Documents Downloads Google Drive Library Movies Music 

Not very useful in that case but here’s another use:

steven$: ls -l $(which node)
lrwxr-xr-x  1 steven  admin  29 Sep 28 16:34 /usr/local/bin/node -> ../Cellar/node/6.7.0/bin/node

This gives me a little me the ls -l information for the path supplied by which node.

Note: The which displays an executable's location


Double quotes in the command line mean that all special characters or expansions will be escaped with the exceptions of the dollar sign “$”, backslash ”\”, and backtick “`” characters.

Single quotes on the other hand suppress all expansions.


Most people know that your command line has a history of past commands that you can search through using the up or down arrows. But there’s a whole bunch of things you can do to make this process easier for you if say you want a command you used 50 commands ago. Bash will in fact save your last 500 commands.

To see all of this history:

$steven: history 
1 ls 
2 pwd 
3 etc...

Now you’ll see numbers in the lefthand column that is unique for each command in your history. To reference those past histories you put an exclamation point before the number.


$steven: !476

This runs the command labeled 476 in your history.

Another cool trick is searching your history. Press ctrl + r and start typing the beginning of the command you want. This will look for the closest match. I found this a bit hard to use if you used similar variations of the same command a lot but it can be very useful in the right situation.


If you’re doing any type of system administration you will likely need to change file permissions at some point. The first thing to understand is there are 3 types of users: Owners, group members, and everyone else.

When you use the: “ls -l” command you’ll see the permissions in the first column. It reads left to right in that order (owners, group members, everyone else). The letters rwx refer to the read, write, and executable permissions.


To set permissions for a file you can use the following format:

chmod [3 octal digits] [file]

The octal digits represent file permissions for all 3 groups. There’s an alternate format to change file permissions but this is the method I prefer and I think if you take a look at the chart below you'll find this to be easy enough. To use the chart just add up the numbers in each column for each type of user.

The octal numeral system, is a base-8 number system, and uses the digits 0 to 7

	   Owner Group	Other
Read	 4	   4	   4
Write    2	 2	     2	
Execute  1     1	   1
777	=	rwxrwxrwx
755	=	rwxr-xr-x
644	=	rw-r--r--
700	=	rwx------
750	=	rwxr-x---


chmod 777 my_file.txt

This gives read, write, and execute permissions to all users.

Hopefully you learned a few new tips or tricks that can help you optimize your daily performance!