Advertisement
Tools & Tips

The Command Line is Your Best Friend

by

The command line can either be your best friend, or your worst enemy. It simply depends on how you use it, and what you use it for. If you're one of the many people who cringe at the mere thought of using the command line, then you've come to the right place!


Command Line Interface?

Yes, it's that white (or green) on black screen, where mysterious text flows and strange commands execute. I know great programmers who never use the CLI; however, I also know basic computer users who do everything in the CLI instead of the graphical user interface (GUI). They have console applications to browse the web and file system, read mail, view images and edit text. They even watch YouTube videos and read PDF files without a GUI!

It's up to each person to find his or her best workflow. Some prefer the GUI, while others enjoy the CLI.

Please Note: The real CLI has little or nothing to do with what you see on TV. Rarely is the CLI realistically portrayed in movies or TV shows.


Terminology

Newcomers to the Unix/Linux world are typically confused, when it comes to the difference between a terminal, a console and a shell.

From the user's perspective, there may be little to no difference between them, but in actuality, the the user uses a console to connect to a terminal, in order to look at the shell running on the computer.

It's up to each person to find his or her best workflow.

In ye olden days, these three items were separate hardware. The console was nothing more than a monitor and keyboard; it had no computing capabilities. It connected to a terminal, via a serial interface, the most common being the RS-232 connector.

A terminal is akin to an end-point to a mainframe. It usually had some computing capabilities and could communicate over a network, or some form of specialized connection, to a mainframe. A terminal also provided administrative rights to the system, which was why it was usually kept in a closed room. The consoles from the employees' area connected to these terminals, allowing them to work without having administrative access to the mainframe.

Consoles and terminals eventually merged in a single device, the most notorious being the VT terminals emulated in modern Linux distributions.

The shell is the actual program capable of reading the user's input and providing the result on the screen. A shell can be textual (like the CLI) or graphical (like Windows' GUI). In today's computing, a shell is much more than a simple interface between the user and system. It is responsible for managing processes, windows, applications, commands and other aspects of the system.

The CLI is a shell that offers a text-based interface to the user.

The shell interprets the commands entered through the command line, and a user can combine multiple commands into a single script. Modern shells have a scripting language of their own, providing the ability to perform complex decisions.

Most modern Linux distributions, as well as Mac OSX, use a shell, called BASH. Solaris and OpenIndiana use KornShell by default, which is another variant of BASH. Please note that this tutorial will focus on BASH.

Windows users can also use BASH. It is distributed with Cygwin and MinGW.


Let's Talk About BASH

Most modern Linux distributions, as well as Mac OSX, use a shell, called BASH.

BASH stands for Bourne Again Shell. It was released in 1989 as a reincarnation of the Bourne Shell, the then default shell on Unix systems. It was programmed by Stephen Bourne and came as a replacement for Thompson Shell, the first ever shell software for UNIX. The old Bourne Shell is still present in some Unix systems. You can usually find it as /bin/sh. However, even that has been replaced by BASH on most modern distributions; both /bin/sh and /bin/bash are executables for BASH.

The BASH Prompt

The one thing that you will always have is BASH's prompt. It is a story in and of itself, and we could spend this entire tutorial on how to configure and personalize it. Instead, we'll only discuss the basics in this tutorial.

csaba@csaba-pc ~/Personal/Programming/NetTuts $

This is what my prompt looks like. The first word, csaba is my username, followed by @ and my computer's hostname, and then the current folder. The character "~" stands for the current user's home directory - /home/csaba, in my case. The line ends with $. Whatever I type after the $ is the command that I want my shell to execute.

Root is Special: If you are root, the prompt ends with # instead of $.

Of course, this is only a simple example; you can put a lot more information in your prompt line. Let's explore some basic examples.

BASH has a set of special variables, PS1, PS2, PS3 and PS4, which control the contents in the prompt at different stages of a program's execution. We will only talk about PS1 in this tutorial. You can check what the PS1 variable contains with the following command:

csaba@csaba-pc ~/Personal/Programming/NetTuts $ echo $PS1
\[\033[01;32m\]\u@\h\[\033[01;34m\] \w \$\[\033[00m\]

What you see here is my prompt, followed by a command echo $PS1 and the output of the command. In BASH, you put the dollar sign before the variable name when you want to read its contents. The echo command simply outputs whatever it receives as a parameter. If the parameter is a variable, its value displays on the screen.

The output represents a format. \[\033[01;32m\] is a color code for green, and \u represents the current user's username. The \h token stands for hostname, and \[\033[01;34m\] is the color code for blue. \w is the current directory, and \[\033[00m\] is a light gray color for whatever follows (the commands I type). Below is a screenshot, so that you can better visualize the result.

There are special characters preceded by "\" that have their own special meaning. Otherwise, "\" denotes an escape character for what follows (as in the color codes). Below is the complete list of special characters that you can use in the BASH prompt, cited from the official BASH manual:

  • \a - an ASCII bell character (07)
  • \d - the date in "Weekday Month Date" format (e.g., "Tue May 26")
  • \D{format} - the format is passed to strftime(3) and the result is inserted into the prompt string; an empty format results in a locale-specific time representation. The braces are required
  • \e - an ASCII escape character (033)
  • \h - the hostname up to the first `.'
  • \H - the hostname
  • \j - the number of jobs currently managed by the shell
  • \l - the basename of the shell's terminal device name
  • \n - newline
  • \r - carriage return
  • Each of these commands are capable of much more than what I covered in this tutorial.

  • \s - the name of the shell, the basename of $0 (the portion following the final slash)
  • \T - the current time in 12-hour HH:MM:SS format
  • \t - the current time in 24-hour HH:MM:SS format
  • \@ - the current time in 12-hour am/pm format
  • \A - the current time in 24-hour HH:MM format
  • \u - the username of the current user
  • \v - the version of bash (e.g., 2.00)
  • \V - the release of bash, version + patch level (e.g., 2.00.0)
  • \w - the current working directory, with $HOME abbreviated with a tilde (uses the value of the PROMPT_DIRTRIM variable)
  • \W - the basename of the current working directory, with $HOME abbreviated with a tilde
  • \! - the history number of this command
  • \# - the command number of this command
  • \$ - if the effective UID is 0, a #, otherwise a $
  • \nnn - the character corresponding to the octal number nnn
  • \\ - a backslash
  • \[ - begin a sequence of non-printing characters, which could be used to embed a terminal control sequence into the prompt
  • \] - end a sequence of non-printing characters

Working with Directories and Files

The things everyone must do in a command line environment is navigate the file system, create, delete, copy and move file system objects, and execute commands. This may be common knowledge to some of you, but let's take a quick look:

csaba@csaba-pc ~ $ mkdir ~/tmp/NetTuts
csaba@csaba-pc ~ $ cd ~/tmp/NetTuts/
csaba@csaba-pc ~/tmp/NetTuts $ mkdir ./AnotherDir
csaba@csaba-pc ~/tmp/NetTuts $ mkdir ./SecondDir
csaba@csaba-pc ~/tmp/NetTuts $ touch ./SecondDir/aFile
csaba@csaba-pc ~/tmp/NetTuts $ touch ./SecondDir/AnotherFile
csaba@csaba-pc ~/tmp/NetTuts $ cd ./SecondDir/
csaba@csaba-pc ~/tmp/NetTuts/SecondDir $ pushd ~/tmp/NetTuts
~/tmp/NetTuts ~/tmp/NetTuts/SecondDir
csaba@csaba-pc ~/tmp/NetTuts $ ls -al
total 16
drwxr-xr-x 4 csaba csaba 4096 Feb 19 21:09 .
drwx------ 7 csaba csaba 4096 Feb 19 21:09 ..
drwxr-xr-x 2 csaba csaba 4096 Feb 19 21:09 AnotherDir
drwxr-xr-x 2 csaba csaba 4096 Feb 19 21:09 SecondDir
csaba@csaba-pc ~/tmp/NetTuts $ popd
~/tmp/NetTuts/SecondDir
csaba@csaba-pc ~/tmp/NetTuts/SecondDir $ ls -al
total 8
drwxr-xr-x 2 csaba csaba 4096 Feb 19 21:09 .
drwxr-xr-x 4 csaba csaba 4096 Feb 19 21:09 ..
-rw-r--r-- 1 csaba csaba    0 Feb 19 21:09 aFile
-rw-r--r-- 1 csaba csaba    0 Feb 19 21:09 AnotherFile
csaba@csaba-pc ~/tmp/NetTuts/SecondDir $

A line-by-line explanation:

If you are root, the prompt ends with # instead of $.

  1. Create a directory called NetTuts under /home/csaba/tmp.
  2. Change current directory to the newly created directory.
  3. Create a directory called "AnotherDir" inside the current directory.
  4. Create a directory called "SecondDir" inside the current directory.
  5. Create two empty files inside "SecondDir" using the touch command.
  6. Change current directory to SecondDir.
  7. Use pushd to change directory to ~/tmp/NetTuts in order to put our current directory on a stack.
  8. List all files in ~/tmp/NetTuts
  9. Return to our previous directory by issuing a popd command, which fetches (and removes) the top directory from the stack.
  10. List again the contents and see the two files we created a few steps above.

Of course, you have an almighty file manager for the command line, called Midnight Commander. Just execute the mc commdn to start using it. It also has a built-in text editor (with code highlighting) for a large number of languages, as well as smart indentation and other features. It's not a full blown editor, in fact it's a rather simple tool for simple and quick edits. You can simply select any file and hit F4, or you can open a file directly in the editor without starting mc.

csaba@csaba-pc ~/tmp/NetTuts/SecondDir $ mcedit ./aFile

Input/Output

Every command must communicate with the command line environment. Commands need input and provide output. Standard Input refers to source from where a command can read information. This is the keyboard by default, and it's frequently referred to as "stdin". Standard Output refers to the place where a command's output will be sent. By default, this is the current console, and its usually referred to as "stdout". Standard Error refers to the place where a command outputs its errors. This is the current console by default, and many refer to it as "stderr".

What we defined so far simply states that a command can read from the keyboard and output its results, both good and bad, to the screen.

In Unix (and similar systems) everything is a file. Your keyboard is a file, your mouse is a file, your screen is a file, programs are in files, text is in files, etc.

A File Descriptor is an integer that the operating system's kernel uses to reference open files. Every system has at least three file descriptors:

  • Descriptor no. 0 - standard input.
  • Descriptor no. 1 - standard output.
  • Descriptor no. 2 - standard error.

Redirections

Unix systems have a very powerful feature: because everything is a file, you can reference and redirect everything from one place to another. The redirection operators are < for stdin and > for stdout. So, if you want a command to read information from the keyboard, you can do something like this:

$ someCommand <

But what if you want your command to read from a file? Well you can redirect a file into its stdin, like this:

$ someCommand < /your/file.txt

If you want your command's output to go into a file, you can use the > operator. For example we've seen how to list files in a folder:

csaba@csaba-pc ~/tmp/NetTuts/SecondDir $ ls -al
total 8
drwxr-xr-x 2 csaba csaba 4096 Feb 19 21:09 .
drwxr-xr-x 4 csaba csaba 4096 Feb 19 21:09 ..
-rw-r--r-- 1 csaba csaba    0 Feb 19 21:09 aFile
-rw-r--r-- 1 csaba csaba    0 Feb 19 21:09 AnotherFile
csaba@csaba-pc ~/tmp/NetTuts/SecondDir $

You can send that result to a file with the following command:

csaba@csaba-pc ~/tmp/NetTuts/SecondDir $ ls -al > ./ThirdFile

The contents of ThirdFile is:

total 12
drwxr-xr-x 2 csaba csaba 4096 Feb 24 00:06 .
drwxr-xr-x 4 csaba csaba 4096 Feb 19 21:09 ..
-rw-r--r-- 1 csaba csaba   12 Feb 19 21:19 aFile
-rw-r--r-- 1 csaba csaba    0 Feb 19 21:09 AnotherFile
-rw-r--r-- 1 csaba csaba    0 Feb 24 00:06 ThirdFile

Let's say we want to navigate to the parent folder, list all its files, and use a command to append the list to the existing file. The > operator redirects output to a file and overwrites that file; so we can't use it. We can, however, use >> (a double >) to append new data to an existing file.

csaba@csaba-pc ~/tmp/NetTuts/SecondDir $ cd ..
csaba@csaba-pc ~/tmp/NetTuts $ ls -al
total 16
drwxr-xr-x 4 csaba csaba 4096 Feb 19 21:09 .
drwx------ 7 csaba csaba 4096 Feb 19 21:09 ..
drwxr-xr-x 2 csaba csaba 4096 Feb 19 21:09 AnotherDir
drwxr-xr-x 2 csaba csaba 4096 Feb 24 00:06 SecondDir
csaba@csaba-pc ~/tmp/NetTuts $ ls -al >> ./SecondDir/ThirdFile

And our file's content is:

total 12
drwxr-xr-x 2 csaba csaba 4096 Feb 24 00:06 .
drwxr-xr-x 4 csaba csaba 4096 Feb 19 21:09 ..
-rw-r--r-- 1 csaba csaba   12 Feb 19 21:19 aFile
-rw-r--r-- 1 csaba csaba    0 Feb 19 21:09 AnotherFile
-rw-r--r-- 1 csaba csaba    0 Feb 24 00:06 ThirdFile
total 16
drwxr-xr-x 4 csaba csaba 4096 Feb 19 21:09 .
drwx------ 7 csaba csaba 4096 Feb 19 21:09 ..
drwxr-xr-x 2 csaba csaba 4096 Feb 19 21:09 AnotherDir
drwxr-xr-x 2 csaba csaba 4096 Feb 24 00:06 SecondDir

Input/Output Redirections

We can combine our knowledge and redirect stderr, stdin and stdout in different ways. In fact the commands below are doing the same thing:

csaba@csaba-pc ~/tmp/NetTuts $ ls -al > ./SecondDir/ThirdFile
csaba@csaba-pc ~/tmp/NetTuts $ ls -al 1> ./SecondDir/ThirdFile

In the second command, we specified the source as standard output (1>) right before the redirection. Please also note that there is no space between 1 and >. In fact, placing a space between the two characters makes 1 a parameter and > would automatically imply redirection of standard output. The two expressions below do the same thing and are different from the ones above:

csaba@csaba-pc ~/tmp/NetTuts $ ls -al 1 > ./SecondDir/ThirdFile
csaba@csaba-pc ~/tmp/NetTuts $ ls -al 1 1> ./SecondDir/ThirdFile

Of course, these result in an error: "ls: cannot access 1: No such file or directory" - unless you really have a directory named 1. This makes us wonder about the next steps we can take: redirecting errors.

csaba@csaba-pc ~/tmp/NetTuts $ ls -al inexistenFilder > ./SecondDir/ThirdFile
ls: cannot access inexistenFilder: No such file or directory
csaba@csaba-pc ~/tmp/NetTuts $ ls -al inexistenFilder 2> ./SecondDir/ThirdFile

As you can see, the first command outputs stderr in the console and redirects stdout to a file. The result of the first command is an empty file and a message on the screen. The second command, however, redirects the errors to our file. The result is that if there were any outputs on standard output, they would go on the screen and errors would go to the file.

A Real Life Example for I/O Redirection

You basically have two options when you need to search for files in the console. The first is the locate command. It is usually, but not necessarily, installed on many modern Linux distributions. The updatedb command indexes your files and locate uses that database to find your files. It does not actually do a real-time search, it simply looks up indexes in a database. That's why this application is usually scheduled for a daily updatedb.

The second command is called, well, find.

This command performs a real-time search. It is more accurate than locate, but is obviously much slower. Let's play with it a little:

csaba@csaba-pc ~/tmp/NetTuts $ ls -al
total 16
drwxr-xr-x 4 csaba csaba 4096 Feb 19 21:09 .
drwx------ 7 csaba csaba 4096 Feb 19 21:09 ..
drwxr-xr-x 2 csaba csaba 4096 Feb 19 21:09 AnotherDir
drwxr-xr-x 2 csaba csaba 4096 Feb 24 00:06 SecondDir
csaba@csaba-pc ~/tmp/NetTuts $ ls -al ./SecondDir/
total 16
drwxr-xr-x 2 csaba csaba 4096 Feb 24 00:06 .
drwxr-xr-x 4 csaba csaba 4096 Feb 19 21:09 ..
-rw-r--r-- 1 csaba csaba   12 Feb 19 21:19 aFile
-rw-r--r-- 1 csaba csaba    0 Feb 19 21:09 AnotherFile
-rw-r--r-- 1 csaba csaba   61 Feb 24 00:23 ThirdFile
csaba@csaba-pc ~/tmp/NetTuts $ find . -name ThirdFile
./SecondDir/ThirdFile

I printed the two ls commands so that you can see the directory structure. The third command is our find. It has a complex parameter system that I will not detail here, but the above example demonstrates the most common use of find. The first parameter, ., is the directory in which we want to search.

Tip: . refers to the current directory. .. refers to the parent directory.

The second parameter we used for find was -name, followed by a file's name. We can use ? and * in the -name parameter to broaden our search:

csaba@csaba-pc ~/tmp/NetTuts $ find . -name ?File
./SecondDir/aFile
csaba@csaba-pc ~/tmp/NetTuts $ find . -name *File
./SecondDir/aFile
./SecondDir/AnotherFile
./SecondDir/ThirdFile

? stands for any single character, and * refers to any number of any characters.

Next, we will create a directory and make it unreadable by our user. We have not yet reviewed permissions, but don't worry, we will shortly. For now, simply try the following:

csaba@csaba-pc ~/tmp/NetTuts $ mkdir ThirdDir
csaba@csaba-pc ~/tmp/NetTuts $ chmod 000 ThirdDir
csaba@csaba-pc ~/tmp/NetTuts $ find . -name *File
./SecondDir/aFile
./SecondDir/AnotherFile
./SecondDir/ThirdFile
find: `./ThirdDir': Permission denied

I wanted you to not have permission to a directory so that I can demonstrate what find outputs in this case. It tries to access all the directories and search for files that match the given pattern. When it can't access a directory, it outputs a message. This is OK when you have one or two messages, but try to search for something starting from the root folder as an ordinary user. You will get hundreds of such error messages and probably only one or two search results. You don't want to miss the results; you want to get rid of the error messages.

csaba@csaba-pc ~/tmp/NetTuts $ find . -name *File 2> /dev/null
./SecondDir/aFile
./SecondDir/AnotherFile
./SecondDir/ThirdFile

We redirected stderr into /dev/null. This points to... well nothing. Whatever you throw into /dev/null will simply vanish. It is common practice to send errors there when you don't want to see them. If you prefer your results in a file, and your errors sent to /dev/null, you can use multiple redirections:

csaba@csaba-pc ~/tmp/NetTuts $ find . -name *File 2> /dev/null 1>./SecondDir/ThirdFile
csaba@csaba-pc ~/tmp/NetTuts $

As you can see, this command outputs nothing to the screen because both errors and standard output are sent to different files. But what if you want both in the same file? Well, you can send stderr into stdout and then send stdout to a file:

find . -name *File 1>./SecondDir/ThirdFile 2>&1

Redirections are interpreted from right to left. So the first one that happens is 2>&1, which redirects standard error to standard output. Then 1>./SecondDir/ThirdFile redirects standard output (with the errors already in it) into the specified file.


Let's Talk About Permissions

The permissions discussed in this tutorial are applicable to *nix operating systems. I am not that familiar with the latest Windows versions, but Microsoft uses a different concept for permissions on their file systems.

Users and Groups

There can be several users on the same computer. In fact, several applications register their own special user and use it to run the program in a restricted environment. Each user can be identified by their name and/or their ID, also known as UID.

You can find the list of the currently existing users in the file /etc/passwd.

Groups are listed in the file /etc/group. A group has a name and ID (known as GID), and a group is a container of zero or more users. Each user usually has at least one corresponding group, which has the same name as the user.

The Owner

Files have owners, and the user that creates a file is, by default, its owner. Directories are just special files, and they have the same owner and permission rules as ordinary files.

csaba@csaba-pc ~/tmp/NetTuts $ ls -al
total 20
drwxr-xr-x 5 csaba csaba 4096 Feb 24 00:44 .
drwx------ 7 csaba csaba 4096 Feb 19 21:09 ..
drwxr-xr-x 2 csaba csaba 4096 Feb 19 21:09 AnotherDir
drwxr-xr-x 2 csaba csaba 4096 Feb 24 00:06 SecondDir
d--------- 2 csaba csaba 4096 Feb 24 00:44 ThirdDir

In our ls -al command, the owner of each result is specified as "user group" ("csaba csaba" in our example). We will now change the owner of AnotherDir with the following:

csaba@csaba-pc ~/tmp/NetTuts $ chown csaba:users ./AnotherDir/
csaba@csaba-pc ~/tmp/NetTuts $ ls -al
total 20
drwxr-xr-x 5 csaba csaba 4096 Feb 24 00:44 .
drwx------ 7 csaba csaba 4096 Feb 19 21:09 ..
drwxr-xr-x 2 csaba users 4096 Feb 19 21:09 AnotherDir
drwxr-xr-x 2 csaba csaba 4096 Feb 24 00:06 SecondDir
d--------- 2 csaba csaba 4096 Feb 24 00:44 ThirdDir

The chown command means "change owner", and it has a simple syntax: chown user:group path. A user can only change the group ownership to one of the groups it is a member of, and an ordinary user cannot change ownership to another user it cannot access. Of course, a user with administrative privileges, such as "root", can change the ownership of any file and set it to any user and group.

There are three types of file permissions:

  • r - read
  • w - write
  • x - execute

Please Note: The contents of a directory can be listed, if it has execute permissions.

Refer to the previous ls command example. The permissions for each file system object are displayed at the beginning of each line (those rwx characters). Each permission can be set (thus marked with a letter) or not set (marked with a dash: "-").

The three permission types are applied to three categories:

  • User - the rights for the owner user.
  • Group - the permissions for the owner group
  • Others - the permissions for other users attempting to access our file or folder.

The directory called ThirdDir has no permissions, so not even its owner can access it.

chown: changing ownership of ‘./AnotherDir/’: Operation not permitted
csaba@csaba-pc ~/tmp/NetTuts $ ls -al ./ThirdDir/*
ls: cannot access ./ThirdDir/*: Permission denied

But its owner does have the rights to change its permissions:

csaba@csaba-pc ~/tmp/NetTuts $ chmod +rwx ./ThirdDir/
csaba@csaba-pc ~/tmp/NetTuts $ ls -al ./ThirdDir
total 8
drwxr-xr-x 2 csaba csaba 4096 Feb 24 00:44 .
drwxr-xr-x 5 csaba csaba 4096 Feb 24 00:44 ..
csaba@csaba-pc ~/tmp/NetTuts $ ls -al
total 20
drwxr-xr-x 5 csaba csaba 4096 Feb 24 00:44 .
drwx------ 7 csaba csaba 4096 Feb 19 21:09 ..
drwxr-xr-x 2 csaba users 4096 Feb 19 21:09 AnotherDir
drwxr-xr-x 2 csaba csaba 4096 Feb 24 00:06 SecondDir
drwxr-xr-x 2 csaba csaba 4096 Feb 24 00:44 ThirdDir

The chmod command sets global permissions on a file system object, and its syntax is: chmod +/-rights path. Using a + means you enable a right, and - means you remove a right. You can specify any combination of rights. In the previous example, we added read, write and execute permissions to ThirdDir.

Please Note: Read and execute permissions defined this way are applied to owner, group and others. Write permissions are applied only to the current user.

csaba@csaba-pc ~/tmp/NetTuts $ chmod +r-w ./ThirdDir/
csaba@csaba-pc ~/tmp/NetTuts $ ls -al
total 20
drwxr-xr-x 5 csaba csaba 4096 Feb 24 00:44 .
drwx------ 7 csaba csaba 4096 Feb 19 21:09 ..
drwxr-xr-x 2 csaba users 4096 Feb 19 21:09 AnotherDir
drwxr-xr-x 2 csaba csaba 4096 Feb 24 00:06 SecondDir
dr-xr-xr-x 2 csaba csaba 4096 Feb 24 00:44 ThirdDir

In this second example, we selectively enabled read permissions, removed write permissions and left execute permissions untouched.

But at some point, everything in computing comes down to a binary string. The chown command allows you to easily specify permissions using a decimal representation of the binary permissions.

  • rwx: Each bit is set to 1: 111. Which in decimal is 7.
  • rw-: Is represented as 110. Which in decimal is 6.
  • r-x: Is represented as 101. Which in decimal is 5.
  • r--: Is represented as 100. Which in decimal is 4.
  • -wx: Is represented as 011. Which in decimal is 3.
  • -w-: Is represented as 010. Which in decimal is 2.
  • --x: Is represented as 001. Which in decimal is 1.
  • ---: Is represented as 000. Which in decimal is 0.

The chown command can accept a string of three numbers between 0 and 7. Each digit represents the rights for a specific category in order: user, group, others.

csaba@csaba-pc ~/tmp/NetTuts $ chmod 765 ./ThirdDir/
csaba@csaba-pc ~/tmp/NetTuts $ ls -al
total 20
drwxr-xr-x 5 csaba csaba 4096 Feb 24 00:44 .
drwx------ 7 csaba csaba 4096 Feb 19 21:09 ..
drwxr-xr-x 2 csaba users 4096 Feb 19 21:09 AnotherDir
drwxr-xr-x 2 csaba csaba 4096 Feb 24 00:06 SecondDir
drwxrw-r-x 2 csaba csaba 4096 Feb 24 00:44 ThirdDir

This command sets read, write and execute rights for the owner, read, write, and not-execute for the group, and read, execute, and not-write for others.


The Cat, Sed, and Pipe

Here are a few of the most useful commands.

Cat

This command lets you read the contents of a file. Simply provide the filename as a parameter, and it outputs the file's contents to stdout.

csaba@csaba-pc ~/tmp/NetTuts $ cat ./SecondDir/ThirdFile
./SecondDir/aFile
./SecondDir/AnotherFile
./SecondDir/ThirdFile
find: `./ThirdDir': Permission denied

Grep

Grep searches for a pattern and outputs the matching lines. You can optionally specify a file to search as the third parameter:

csaba@csaba-pc ~/tmp/NetTuts $ grep "AnotherFile" ./SecondDir/ThirdFile
./SecondDir/AnotherFile

Adding the --color option highlights the matched word in the the resulting lines.

Pipe

The pipe is represented by the | character; it takes one command's output and feeds it to a second command. This may sound simple, but it's a huge thing. That single character has tens of thousands of lines of code behind it so that you can do this:

csaba@csaba-pc ~/tmp/NetTuts $ cat ./SecondDir/ThirdFile | grep "Another"
./SecondDir/AnotherFile

This actually runs the cat command, and instead of outputing the results to stdout, it feeds that output to grep. The grep command uses that data and searches for the string "Another". The result is identical to our previous example.

The History of UNIX: This is an old video from AT&T. It is a great video, but scroll to 4:56, if you are only interested in the PIPEs.

Sed

The sed command allows you to execute regular expressions on its input. It can read from a file or be used in a piped command. It outputs the result to stdout.

csaba@csaba-pc ~/tmp/NetTuts $ cat ./SecondDir/ThirdFile | grep "Another" | sed -e "s/AnotherFile/MyFile/"
./SecondDir/MyFile

This example adds a sed to our previous command. With the help of sed, we replaced the string "AnotherFile" with "MyFile" in the output of the cat...grep. Pretty cool, right?

The sed command can accept several parameters. Specifying the -e argument executes the regular expression on its input. If you are not familiar with regular expressions, check out these other Nettuts+ tutorials: Introducing "Regular Expressions: Up and Running" or Regular Expressions Cheat Sheets.


Defining Your Own Commands

Let's imagine that you execute the following ssh connection command frequently:

csaba@csaba-pc ~/tmp/NetTuts $ ssh my_username@complicated.server.address.com -p 8743

You can shorten this by creating a custom command, say sshcon. You could create your own commands by using an alias. Alias syntax is in the form of: alias shorthand='original_command'.

csaba@csaba-pc ~/tmp/NetTuts $ alias sshcon='ssh my_username@complicated.server.address.com -p 8743'

Running sshcon executes the more complicated ssh command. But aliases are temporary; they're forgotten when you log out. One possible solution is to edit your .bashrc file.

.bashrc and .bash.profile

The .bashrc file is usually located in your home directory. This file lets you specify any command(s) you want to execute whenever you open a console or log into a shell. Let's add the aforementioned sshcon alias to this file.

csaba@csaba-pc ~/tmp/NetTuts $ mcedit ~/.bashrc

Add your code to the end of the file, hit F2 to save the file, and then ESC twice to close the file. Press CTRL+D to log out from the shell. Open another shell and try your alias command. Voila.

Some operating systems, such as Solaris, may not have a ~/.bashrc file. In this case, you can do your magic by editing ~/.bash_profile. In fact, ~/.bash_profile is always present on all systems.

The Hidden Files: Files that begin with a dot (.) denote a hidden file.


A Little Networking

Let's play with the network a little.

Ping

The ping command is an easy way to check if a server is up and accessible.

csaba@csaba-pc ~/tmp/NetTuts $ ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=47 time=44.0 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=47 time=65.6 ms
^C
--- 8.8.8.8 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 44.081/54.871/65.661/10.790 ms
csaba@csaba-pc ~/tmp/NetTuts $ ping inexistent.server
ping: unknown host inexistent.server

Its syntax is easy: ping IP_address_or_name. If the server is accessible, you will see a list of reply lines with details. If it's not, an error message states the problem.

Traceroute

The traceroute command displays the route a packet takes from your computer to the destination device.

csaba@csaba-pc ~/tmp/NetTuts $ traceroute 8.8.8.8
traceroute to 8.8.8.8 (8.8.8.8), 30 hops max, 60 byte packets
 1  192.168.111.1 (192.168.111.1)  0.239 ms  0.322 ms  0.317 ms
 2  * * *
 3  95.77.39.65 (95.77.39.65)  45.754 ms  45.887 ms  46.024 ms
 4  ro-cj01a-rd4-xe-1-2-1-v1643.upcnet.ro (84.116.216.1)  83.121 ms ro-cj01a-rd4-xe-1-2-0-v1642.upcnet.ro (84.116.225.253)  83.289 ms ro-cj01a-rd4-xe-1-3-0-v1713.upcnet.ro (84.116.217.26)  83.119 ms
 5  84.116.217.93 (84.116.217.93)  83.153 ms 84.116.217.85 (84.116.217.85)  77.407 ms  77.350 ms
 6  84-116-131-53.aorta.net (84.116.131.53)  77.327 ms  53.442 ms  53.357 ms
 7  84.116.132.174 (84.116.132.174)  53.211 ms  48.923 ms  53.186 ms
 8  72.14.219.9 (72.14.219.9)  85.040 ms 72.14.214.29 (72.14.214.29)  67.289 ms  72.216 ms
 9  209.85.241.110 (209.85.241.110)  48.129 ms  47.389 ms 209.85.240.64 (209.85.240.64)  45.096 ms
10  72.14.239.62 (72.14.239.62)  47.254 ms 72.14.236.68 (72.14.236.68)  51.770 ms 72.14.239.62 (72.14.239.62)  43.242 ms
11  209.85.254.118 (209.85.254.118)  46.137 ms 209.85.254.116 (209.85.254.116)  52.165 ms 209.85.254.114 (209.85.254.114)  102.070 ms
12  * * *
13  google-public-dns-a.google.com (8.8.8.8)  47.471 ms  47.986 ms  43.645 ms

Routing Table

Both *nix and Windows have a route command. And despite their slight differences in syntax, their functionality is basically the same. This command allows us to see the current routing table of the system, and if necessary, add/delete static routes.

csaba@csaba-pc ~/tmp/NetTuts $ route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         192.168.111.1   0.0.0.0         UG    0      0        0 eno1
loopback        localhost       255.0.0.0       UG    0      0        0 lo
192.168.111.0   *               255.255.255.0   U     1      0        0 eno1

The first column is the destination, the target of a network connection or communication. The term "default" means anything not matched by something else or sent here. Loopback is our virtual local device, the one having the IP 127.0.0.1. This IP always refers to the local, machine and it is present on all operating systems ([ed] there's no place like 127.0.0.1).

The second column is the gateway the connection uses to reach its destination. The first line displays my default gateway as 192.168.111.1. The second line for loopback goes to localhost, and the third line goes to *, no gateway is necessary for acessing our own network.

The third interesting thing here is the last column: "Iface". It specifies the interface used to communicate to the specific destination. In our example, loopback communication goes over the loopback interface lo. Everything else goes through the eno1 interface.

Tip: If you find no route command, try using netstat -nr. It should produce similar output.

Network Configuration

If you want a quick glance at your network configuration, just type ifconfig in the command line.

csaba@csaba-pc ~/tmp/NetTuts $ ifconfig
eno1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.111.10  netmask 255.255.255.0  broadcast 192.168.111.255
        inet6 fe80::4e72:b9ff:fef6:c9ff  prefixlen 64  scopeid 0x20<link>
        ether 4c:72:b9:f6:c9:ff  txqueuelen 1000  (Ethernet)
        RX packets 2935016  bytes 696255521 (664.0 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 5586410  bytes 6331639146 (5.8 GiB)
        TX errors 0  dropped 0 overruns 0  carrier 1  collisions 0
        device interrupt 17

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 16436
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 0  (Local Loopback)
        RX packets 7396  bytes 599533 (585.4 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 7396  bytes 599533 (585.4 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

There is a lot of information here. First, we have two sections, each for a network adapter. My wired network card is called eno1 on my system. You may see things like e1000g0, eth0, en0 or other names. Wireless network devices usually (but not always) begin with a "w".

On the same line is the current status of the interface. In this example, the interface is up, broadcasting, running, etc. The second line is for the IPv4 IP address, netmask and broadcast. The third line is very similar but for IPv6. The forth line, starting with "ether", is the MAC address of the network card, and the remaining lines display data transfer statistics.

Current Network Connections

Another useful command is netstat. It can list all the network connections to the system, as well as the IPs, interfaces and ports the system listens on. Here is a part of netstat's output on my system. I shortened it to eliminate irrelevant information:

csaba@csaba-pc ~/tmp/NetTuts $ netstat -an
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN
tcp        0      0 127.0.0.1:631           0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:59017           0.0.0.0:*               LISTEN
tcp        0     40 192.168.111.10:59017    109.99.97.81:53681      ESTABLISHED
tcp        0      0 192.168.111.10:51137    109.99.97.81:55175      TIME_WAIT
tcp        0      0 192.168.111.10:34715    173.194.70.109:993      ESTABLISHED
tcp        0      0 192.168.111.10:34722    173.194.70.109:993      ESTABLISHED
tcp        0      1 192.168.111.10:42876    86.162.58.4:7055        LAST_ACK
tcp6       0      0 :::111                  :::*                    LISTEN
tcp6       0      0 :::4434                 :::*                    LISTEN
tcp6       0      0 :::59017                :::*                    LISTEN

Each line represents a connection in a specific state. In this example, you can see connections in listening states (see the first line, port 22, my ssh server), established states, waiting states and so on.


Final Thoughts

So there you have it: some of the most used CLI commands! Naturally, each of these commands are capable of much more than what I've covered in this tutorial. I hope I've shed a bit of light on some of these CLI mysteries. Thanks for reading!

Related Posts
  • Computer Skills
    App Training
    Getting Spiffy With PowerlinePowerline
    That line at the bottom of your editor and the prompt for your favorite shell have one thing in common: information! But, it's not always clear, and it's often hard to change. It's much easier now than ever before to do just that with Powerline. I'll show you how easy it is to take charge of the status line and make it into what you want it to be.Read More…
  • Computer Skills
    Alfred
    Alfred DebuggingAlfred400
    No matter how hard I try, I still have problems with scripts that I write. No matter the approach taken, mistakes in typing, logic, or both will cause programs to not behave the way expected. Debugging is the art of finding and removing these mistakes. In Alfred, debugging is even harder due to the scripts being executed in a sub-process. You need the skills this tutorial will teach.Read More…
  • Computer Skills
    Productivity
    How to Manage Your Tasks with Todo.txtTodo txt preview
    Todo.txt is the world's simplest to-do list tool, and it's simply a plain text file. Here's how to get started managing your tasks in plain text, and how to use the apps and command line interface to Todo.txt to get the most out of this somewhat geeky yet powerful productivity tool.Read More…
  • Code
    Web Development
    Refactoring Legacy Code: Part 1 - The Golden MasterRefactoring wide retina preview
    Learn techniques for how to deal with complex and complicated unknown legacy code, how to understand it, and finally writing the Golden Master tests for future changes.Read More…
  • Code
    WordPress
    An Introduction To Deploying WordPress with MinaImage400
    As a PHP application, WordPress is usually deployed by a very old method: uploading files via FTP. We have some deployment tools, but they often requires some type of Ruby skill. For example, one popular, powerful tool is Capistrano, but it's also very heavy with many Ruby/Rails related features. I also think that it's little bit tricky to install Capistrano for a PHP developer without any Ruby knowledge. So what options do we have as WordPress developers? In this tutorial, I will introduce you Mina: A small, light tool aims to fast deployment and server automation.Read More…
  • Code
    PHP
    Aspect-Oriented Programming in PHP with Go!Aop php go preview
    The concept of Aspect-Oriented Programming (AOP) is fairly new to PHP. There's currently no official AOP support in PHP, but there are some extensions and libraries which implement this feature. In this lesson, we'll use the Go! PHP library to learn AOP in PHP, and review when it can be helpful. Read More…