© Brian Schell 2019
B. SchellComputing with the Raspberry Pihttps://doi.org/10.1007/978-1-4842-5293-2_5

5. Using the Command-Line Tools

Brian Schell1 
(1)
Flint, MA, USA
 

Over the past two decades, we’ve all gotten used to using GUI apps and desktops, but before that, everything was done in text mode on terminal screens. If you remember the days of MS-DOS or UNIX, then you know the drill. It was all command line, all the time. And somehow, we still managed to get our work done.

The simple fact is that in many ways, sticking with only the command line is often much faster and more efficient. For example, to save a file in the GUI, you need to reach over to the mouse, move the mouse to the File menu, click the Save command, then move your hand back to the keyboard and resume typing. That’s a lot of moving and interaction. Or you could hit Ctrl-S on the keyboard instead. It’s a trade-off. It’s faster using the keyboard, but you have to spend the time to learn it. Repeating this time savings hundreds of times a day really can add up to more time available for other things.

Many text-based apps don’t rely on, or even support, the mouse. Keyboard commands are usually considered “power user tricks” today, but without the mouse, they become a necessity. Productivity skyrockets when you can keep both hands on the keyboard at all times.

Of course, if you are into desktop publishing or video editing, then you really do need graphical tools. Some things just need the GUI. On the other hand, there are many, many tasks that can be done just as well, if not more efficiently, using only the keyboard. If you thought using the Raspberry Pi as your only computer was a fun challenge, try doing it all in text mode!

In this chapter, we’ll look at some of the basic tools that are used to get things done in text mode. This is not a comprehensive tutorial on Linux commands, but we do look at some of the commands, as well as tools you can use along with or sometimes instead of those commands. We’ll first look at Tmux, an app that lets you control multiple “windows” of text at once; then we’ll look at a better terminal app than the one included in Raspbian; and finally, we will look at two file managers that will make your experience moving, copying, backing up, and deleting files much easier. Last, we’ll review some of the basic Linux/Unix file commands that let you manually copy files, move them, delete them, and so forth.

Spicing Up the Command Line

You probably picture the command line as a black screen with a few lines of complex and obscure green text on it. And if that’s what you want, you can certainly do it that way, but there are numerous tools that make staying in the text mode much more like running a windowing GUI. The app Tmux gives you multiple windows. Terminator gives you nice color schemes, font choices, and a different way to split up your screen. Midnight Commander and Ranger make file operations easier and more powerful than trying to memorize a bunch of commands. We’ll look at all these and spice up that boring command line!

Tmux

Tmux Details:

Installation: sudo apt install tmux

Run command: tmux

Dotfile: ~/.tmux.conf

Help: man tmux

Web site: https://github.com/tmux/tmux

With a GUI like Windows or MacOS, or even Raspbian’s desktop, when you want to run more than one app at a time, you simply run each app in its own little window. You can position these windows next to each other, overlap them if you want, or minimize them completely. With text-mode terminal apps, you only have one screen, so you need to split that screen up into sections and run one app in each section. Effectively, you get the same result, but it requires a little more planning in advance. Figure 5-1 shows two apps running in a single window using an app called Tmux.
../images/485525_1_En_5_Chapter/485525_1_En_5_Fig1_HTML.jpg
Figure 5-1

Tmux in use

Tmux is what is known as a “terminal multiplexer.” That’s a fancy way of saying it splits your terminal window into smaller panes that each can run a separate program. Figure 5-1 shows a single terminal window running two apps: Vim on the left and a directory listing on the right. This is all done through Tmux.

It doesn’t look like much; probably all you will notice is a colored bar at the bottom of the window. This is typical of command-line apps; they often don’t have fancy menus.

You control Tmux by pressing the Tmux “command key,” which by default is Ctrl-B. To make something happen, you press Ctrl-B and some other key depending on what you want to do. For example, to split the screen vertically, as in Figure 5-1, press Ctrl-B and then press %. Note that to get to %, you also have to hold down the Shift key, so that really works out to be Ctrl-B and then Shift-5 (to get % on a US keyboard).

Table 5-1 provides a quick list of the most commonly used Tmux commands. You can split the screen into multiple panes, and/or you can have multiple windows, which are whole screens.
Table 5-1

Various Tmux Commands

Action

Key Combination

Split window vertically

Ctrl-b %

Split window horizontally

Ctrl-b ”

New window

Ctrl-b c

Close window

Ctrl-d OR Ctrl-b x

Kill window

Ctrl-b &

Next window

Ctrl-b n

Previous window

Ctrl-b p

Rename window

Ctrl-b ,

List all windows

Ctrl-b w

Move to window number

Ctrl-b [number]

Next pane

Ctrl-b o

Previous pane

Ctrl-b ;

Show pane numbers

Ctrl-b q

Move pane left

Ctrl-b {

Move pane right

Ctrl-b }

Swap pane locations

Ctrl-b Ctrl-o

Resize pane down

Ctrl-b Ctrl-j

Resize pane up

Ctrl-b Ctrl-k

Resize pane left

Ctrl-b Ctrl-h

Resize pane right

Ctrl-b Ctrl-l

That looks like a lot to remember, but you’ll catch on to them quickly enough with use. In the beginning, all you need to remember is Ctrl-B and then either % or ” to split the window either vertically or horizontally; then use Ctrl-B and the arrow keys to navigate between the panes.

In Chapter 7, I will walk you through my “dotfile” configuration file for Tmux, showing you one easy way to change any of these key bindings and otherwise change Tmux’s behavior.

It’s good to get into the habit of opening the terminal app of your choice and then loading Tmux immediately before anything else. That way, if you find yourself needing another app, you can just pop open another window and have it right there. Of course, you can still open two or three or fifteen different terminal windows if you prefer, but again, by staying inside Tmux, you aren’t slowing yourself down with the mouse.

Note

If you are booting into text mode (with no GUI at all), then Tmux is the only way you can have more than one app running at a time.

Terminator

Terminator Details:

Installation: sudo apt install terminator

Run command: tmux

Dotfile: ~/.tmux.conf

Help: man terminator

Web site: https://gnometerminator.blogspot.com/

While the previous app, Tmux, runs in a general terminal window and splits up what you see in different ways, Terminator is an app that replaces the built-in terminal app itself and runs multiple resizable terminal panels in one window.

Terminator isn’t a text-based app exactly; it’s a replacement for the Linux terminal. If you like the regular terminal app that comes with Raspbian, or if you’d prefer to stick with the more commonly used Tmux method of splitting screens, you can skip this one. On the other hand, I like the customizations of colors and fonts, and I think it just looks nicer, as you can see in Figure 5-2.
../images/485525_1_En_5_Chapter/485525_1_En_5_Fig2_HTML.jpg
Figure 5-2

A trio of Terminator panes

Ranger and Midnight Commander

Ranger Details:

Installation: sudo apt install ranger

Run command: ranger

Dotfile: various files inside ~/.config/ranger/

Help: man ranger

Web site: https://github.com/ranger/rangera

Midnight Commander Details:

Installation: sudo apt install mc

Run command: mc

Dotfile: various files inside /etc/mc/

Help: man mc

Web site: https://midnight-commander.org

Both Midnight Commander and Ranger are file managers. They allow you to easily navigate your computer’s folder hierarchy and copy, move, rename, and delete files, as well as look at previews of the file contents.

It’s completely possible to ignore these two and simply copy files with Unix commands like cp, mv, rm, ls, and so forth; and sometimes it is faster to simply type out your commands. Still, it’s definitely a wise move to learn all the Unix file manipulation commands so you can do things quickly. If you like purely working at a command-line shell, like the one in Figure 5-3, you are always free to do so.

Sometimes, on the other hand, you want to do things with batches of files or more visually browse and navigate your files. Both Midnight Commander and Ranger are good in their own ways, but it’s probably most efficient to pick one or the other and learn to get really good with it.

Ranger has a more “open” feel to it, with two levels of directory in the leftmost two panes and a file preview in the third pane. Movement is fast and highly visual, but there aren’t any controls or menus onscreen—it’s all done through memorized keyboard commands, which slows you down in the beginning. As Figure 5-4 shows, it’s very clean and sparse in what it shows.
../images/485525_1_En_5_Chapter/485525_1_En_5_Fig3_HTML.jpg
Figure 5-3

File listing on the plain command line

../images/485525_1_En_5_Chapter/485525_1_En_5_Fig4_HTML.jpg
Figure 5-4

File listing with Ranger

Midnight Commander, on the other hand, offers a permanent two-column view as shown in Figure 5-5. This is nice for copying files or comparing folders, and there’s even a built-in file editing system. There are also menus at the top of the screen, which are easily navigable by either the keyboard or (gasp!) the mouse.
../images/485525_1_En_5_Chapter/485525_1_En_5_Fig5_HTML.jpg
Figure 5-5

File listing with Midnight Commander

Which one you use is entirely up to you. They both do exactly the same things, but their interfaces are completely different. I generally do most file-moving command things right on the command line—see the next section for more on that. If I want to quickly move to a song or load a text file, I’ll zoom quickly to it in Ranger. When I’m doing something with deeply nested paths, or on the occasion where I don’t know where something is or need to dig through a bunch of files and directories, I’ll use Midnight Commander.

Using the Raspberry Pi As a Terminal

So far in this book, we’ve spent lots of time talking about command-line apps and tools that you can run in a terminal window locally on your Pi computer. We’ve even talked about setting your Pi up to run “headless” with no monitor or keyboard. With a headless setup like this, you access the Pi from some other computer using SSH or VNC Viewer.

Those very same tools will work on large remote computers as well, so if you ever come across some application or process that your RPi really, truly, just cannot handle, you may want to look into running that process on someone else’s computer. You can “rent” a remote server from companies such as Linode.com and DigitalOcean.com for two common examples. These systems are inexpensive, at around $5 a month to start, and they are infinitely scalable.

You can sit at your Raspberry Pi, monitor, and mouse and use SSH and VNC Viewer in the terminal app of your choice to work on remote servers. Back in the early chapters, we looked at the built-in Ubuntu Terminal as well as Terminator, but there are literally dozens of other choices here that you can run from the desktop or full-screen command line. You can even access Mac or Windows PCs in this manner, assuming you have them set up with the proper remote access software. If you can’t solve all your problems with a Pi, perhaps you can use it as a window to a larger machine that can do what you need.

Back in the 1970s–1980s, this kind of client-server pairing was very common. People would use “dumb” terminals to connect to “smart” computers and mainframes to get work done. In the age of personal computers, that way of thinking went away for a few decades. Now, in the modern age of “everything is connected to the Internet,” it’s nothing unusual to do work “in the cloud.”

With this style of work, you don’t need much more than a good terminal program like Terminator, which we’ll discuss later, and VNC Viewer, which comes preinstalled with Raspbian. All the computing power you need resides out in the cloud, and your Pi system is more than enough to do literally anything this way.

SSH

SSH Details:

Installation: sudo apt install ssh

Run command: ssh <hostname>

Dotfile: ~/.ssh/config and /etc/ssh/ssh_config

Help: man ssh

Web site: www.openssh.com/

The SSH app allows you to log in (via text mode) from your terminal screen to another computer’s text-only terminal. Anything you can do in your Raspberry Pi terminal, you can do remotely on another computer as well. If you need more disk space or Internet bandwidth than you can manage at home, you can “rent” computer time at a server farm and “remote in” from your Pi. Figure 5-6 shows my Mac running Midnight Commander, but I’m actually sitting in front of my Pi, while my Mac is in a room upstairs.
../images/485525_1_En_5_Chapter/485525_1_En_5_Fig6_HTML.jpg
Figure 5-6

Accessing my Mac via SSH on the Raspberry Pi

VNC Viewer

VNC Viewer Details:

Installation: (see web site)

Menu location: Raspberry MenuInternet

Help: man vncviewer

Web site: www.realvnc.com/en/connect/download/viewer/raspberrypi/

We discussed setting up the Raspberry Pi as a VNC server back in Chapter 3, and this app does just the opposite; it is the tool you use to log into a computer running the VNC server. It’s like having a complete remote desktop: you can sit in your office and your monitor shows you the desktop of a computer potentially thousands of miles away that you control with your keyboard and mouse.

Figure 5-7 shows my Mac desktop being accessed from my Raspberry Pi desktop computer. Yes, I can really actually run my Mac apps from my Pi desktop; some things are a little slower than they would be natively, but they do work. And the VNC software is FREE on both the Pi and the Mac (and PC as well). This is a super-powerful tool that doesn’t cost a cent.
../images/485525_1_En_5_Chapter/485525_1_En_5_Fig7_HTML.jpg
Figure 5-7

My Mac via VNC Viewer

Essential Linux Commands

For the most part, 90% of what you’ll enter on the command line are the names of apps. We’ll look at many of them in the next chapter. Emacs, Calcurse, Vim, and even more utility-style apps such as apt and shutdown are really just little programs of their own. Sometimes you need to manipulate a file or a directory, and that’s where this section comes in. Note that all of these commands and much more can be done through an interface such as Midnight Commander, so even when living on the command line, some of these are optional. Still, sometimes it’s just faster or more convenient to simply type in commands rather than work with menus.

Clearing the Screen

One of the simplest and most often-used commands in my experience is simply that of cleaning up the messy screen. If you want to clear off the screen, just type
clear

at the command line. You’ll see a refreshed, uncluttered terminal screen. It doesn’t do much, but over the years, I’ve probably typed this command more than anything else.

Quitting the Terminal

If you’re running a terminal window, you can simply type exit to end your session and close the window. If you used the option to boot into full-screen mode, then you can’t just exit the terminal; you’ll need to use the reboot or shutdown commands instead.

Listing Files with ls

ls is short for either “list” or “list structure.” By itself, it simply lists all the files in the current directory.
ls gives the output
Desktop     Downloads   MagPi      Music      'Podsafe Music' Templates
Documents   Dropbox     Main.org   Pictures   Public           Videos
By adding some parameters and options, you can do a lot more:
  • -l shows the list in the long format, displaying Linux file types, permissions, number of hard links, owner, group, size, last-modified date, and filename.

  • -a lists all files in the given directory, including those whose names start with “ . ” (which are hidden files in Unix). By default, these files are excluded from the list.

  • -R recursively lists subdirectories. For example, the command ls -R / would list all files on the system.

  • -d shows information about a symbolic link or directory, rather than about the link’s target or listing the contents of a directory.

  • -t sorts the list of files by modification time.

  • -h prints sizes in human-readable format (e.g., 1K, 234M, 2G, etc.).

So, for one example, we can list all files, including hidden ones, in the current directory, sorted by time, in a detailed format by typing

ls -alt shows us
drwxr-xr-x  4 root root 4096 Jul 28 02:46  ..
drwx------  3 pi   pi   4096 Jul 10 06:10  .vnc
-rw-------  1 pi   pi    217 Jul 10 06:10  .Xauthority
drwx------ 24 pi   pi   4096 Jul 10 06:09  .config
drwxr-xr-x  2 pi   pi   4096 Jul 10 05:52  Documents
drwxr-xr-x 13 pi   pi   4096 Jul 10 05:46  .cache
drwx------  3 pi   pi   4096 Jul 10 05:07  .pp_backup
drwxr-xr-x  2 pi   pi   4096 Jul  9 08:10  .gstreamer-0.10
drwxr-xr-x  3 pi   pi   4096 Jul  9 08:04  .qmmp
drwxr-xr-x  4 pi   pi   4096 Jul  9 05:25  .audacity-data
drwxr-xr-x  3 pi   pi   4096 Jul  9 05:21  Dropbox
drwxr-xr-x  2 pi   pi   4096 Jul  9 05:16  Downloads
-rw-r--r--  1 pi   pi   2363 Jul  9 04:10  Main.org
drwx------  2 pi   pi   4096 Jul  6 11:41  .putty
drwxr-xr-x  2 pi   pi   4096 Jul  6 04:28 'Podsafe Music'
-rw-r--r--  1 pi   pi   3795 Jul  6 04:27  .vimrc
-rw-r--r--  1 pi   pi    185 Jul  6 04:27  .tmux.conf
-rw-r--r--  1 pi   pi   1282 Jul  6 04:27  .muttrc
-rw-r--r--  1 pi   pi   8331 Jul  6 04:27  .emacs
drwxr-xr-x  8 pi   pi   4096 Jul  6 04:27  .vim
drwxr-xr-x  4 pi   pi   4096 Jul  6 04:27  .tmux-themepack
drwxr-xr-x  5 pi   pi   4096 Jul  6 04:27  .mutt
drwx------  3 pi   pi   4096 Jul  6 03:54  .gnome
drwx------  3 pi   pi   4096 Jun 20 08:22  .pki
drwxr-xr-x  2 pi   pi   4096 Jun 20 08:20  Music
drwxr-xr-x  2 pi   pi   4096 Jun 20 08:20  Pictures
drwxr-xr-x  2 pi   pi   4096 Jun 20 08:20  Public
drwxr-xr-x  2 pi   pi   4096 Jun 20 08:20  Templates
drwxr-xr-x  2 pi   pi   4096 Jun 20 08:20  Videos
drwxr-xr-x  2 pi   pi   4096 Jun 20 08:20  Desktop
drwx------  3 pi   pi   4096 Jun 20 08:20  .gnupg
drwxr-xr-x  2 pi   pi   4096 Jun 20 07:55  MagPi
drwxr-xr-x  3 pi   pi   4096 Jun 20 07:55  .local
-rw-r--r--  1 pi   pi    220 Jun 20 07:47  .bash_logout
-rw-r--r--  1 pi   pi   3523 Jun 20 07:47  .bashrc
-rw-r--r--  1 pi   pi    807 Jun 20 07:47  .profile
You can also include a directory or full path to a directory:
ls -al ~
ls -al /home
ls -al /home/brian/Music/Instrumental

The Home Directory: ~

The tilde (~) is a special character that represents the current user’s “home” folder. This way you can generically reference “home” no matter who you are or where you are in the system.

If you do want to specify a location, you can enter it after the options, like this:
ls -al /home/brian/Music

This will specifically list the contents of the Music folder for user “brian.”

Moving Around in the File System

With the ls command , we learned to see what’s in various directories. If you want to move to a directory, you use the cd (Change Directory) command.
cd /home/brian
changes the current directory to the home folder for user brian. Another way to go to the current user’s home folder is cd ~. This works even if you don’t know the current user’s name.
cd /
takes you to the file system’s root, the “root” of the file system “tree.” Everything else is a subdirectory branching from /.
cd ..

Two periods “..” represent the directory located just above the current one. For example, if you are in /home/brian/Music right now, and you want to go to /home/brian, you can simply type cd .. and you’ll move up one level in the structure. Alternately, you could type cd /home/brian, but the two periods are faster to type.

Creating, Deleting, and Listing Directories

Sometimes, you’ll need to create a directory/folder, and for that, you use the mkdir command . You can create a directory in the current directory by typing
mkdir newname
or you can make one anywhere in the file system by including a full pathname before the new directory name:
mkdir /home/pi/Downloads/newname

Note that you have to have access permission in the current directory in order to make a new directory there.

Similarly, to remove a directory, you use the rmdir command:
rmdir /home/pi/Downloads/newname

Removing/deleting a directory requires that the directory be empty. You’ll need to delete any files or subdirectories first.

To see a “diagram” of a Linux file system, you can type the command tree. It will print a representation of all the subdirectories beneath the path that you indicate. For example, to see the structure of everything in your Downloads directory, you could just type
tree ~/Downloads
and get the following:
/home/pi/Downloads
├── DOS Games Pack.zip
├── kali-linux-2019-2a-rpi3-nexmon-img-xz
│   ├── kali-linux-2019.2a-rpi3-nexmon.img.xz
│   └── kali-linux-2019.2a-rpi3-nexmon.img.xz.txt.sha256sum
└── kali-linux-2019.2a-rpi3-nexmon.img.xz.torrent
1 directory, 4 files

Sometimes this can be very useful to see where something is hidden or if there is a directory somewhere you’ve forgotten about.

In addition to the cd command, you can also use the command

pwd to have the system tell you where you are right now. Pwd is short for Present Working Directory.

Similarly, if you need to see what the current username is, you can ask

whoami, and the system will tell you your current username. If you log in regularly under your own username and additionally use the superuser “pi” account as well, this can sometimes resolve confusion over who the computer thinks you are.

Removing (Deleting) Files

Occasionally, you will want to delete a file. For this, you use the remove command, rm. You always need to follow the rm with some file or directory name:
rm /home/brian/junkfile.txt
This will delete the file junkfile.txt from my home directory.
rm /home/brian/download/*

This command uses a “wildcard” character, the asterisk, to denote “everything.” This command will delete all the files in the user brian’s download directory. This will only delete files, not subdirectories. If you want to delete literally everything in a directory, including everything beneath it, you need the -r and -f options:

rm -rf /home/brian/download/*

The -r tells rm to delete files recursively or, in other words, follow any subdirectories and kill them too. The -f option removes confirmation messages. “Are you sure you want to delete this?” kind of messages will no longer appear.

Note that deleting files recursively can be dangerous. The command rm -rf * will delete everything on the computer—every system file, every data file, for all users, assuming you have permission to access those files; this is one reason Linux relies on the permissions system. It’s much safer than letting every user have complete access to everything.

File Ownership with chown

Speaking of permissions and access, sometimes you may want to change the owner of a file. For example, let’s say you created a file, filename.txt, as user “pi” and you want to edit it as user “brian.” You can load the file into an editor, but when you try to save your changes, you will get a message stating that you don’t have permission to do so. Why? Because the operating system thinks it’s not your file.
sudo chown filename.txt brian

This will change the file’s ownership to user brian. Note that this requires the “sudo” command to work; this requirement is so not just anyone can change the ownership of files; it has to be someone with responsibility for the system. Remember Linux was created to be a multiple-user operating system with more than one user able to log into the machine, and all this security stuff is designed around that concept.

Copying and Moving Files

It’s also very common to copy and move files around from one directory to another. The two commands used here are cp and mv, for copy and move, respectively. The cp command copies a file from one directory to another, and when it’s done, there will be a copy of that file in both locations. The mv command does the same thing, but it also deletes the original file, effectively moving the file.
cp /home/brian/download/game.tar /home/brian
will create an exact copy of game.tar in brian’s home directory while leaving the original in the download directory.
mv /home/brian/download/game.tar /home/brian

will create an exact copy of game.tar in brian’s home directory and then delete the original in the download directory.

You can also use wildcards to move all files in a folder somewhere.
mv ~/download/* ~/backups

will move all files in the /home/username/download directory to the /home/username/backups directory.

Man Pages

If in doubt, read the manual! Seriously, one of the things Linux excels at is thorough documentation on command-line apps. If there’s a command you don’t really understand, you can read a full online manual for it. Let’s say Neofetch confuses you; what exactly does it do? What is the purpose?

Assuming you have Neofetch installed, type in
man neofetch
And you’ll get multiple screen pages of documentation, including a synopsis of how to use it, a description explaining the purpose of the app, all the options and parameters that can be used, and anything else that’s important. Usually, there’s far more information than you may want to know. While reading a manual page, you can use the arrow keys to move up and down, the space bar advances a screen “page,” and the Q key on the keyboard quits you back out to the prompt:
NEOFETCH(1)                                   User Commands
NAME
     Neofetch - A fast, highly customizable system info script
SYNOPSIS
     neofetch func_name --option "value" --option "value"
DESCRIPTION
     Neofetch  is  a  CLI  system information tool written in BASH. Neofetch displays information about
     your system next to an image, your OS logo, or any ASCII file of your choice.
     NOTE: Every launch flag has a config option.
OPTIONS
   INFO:
       func_name
              Specify a function name (second part of info() from config) to quickly  display  only  that
              function's information.
              Example: neofetch uptime --uptime_shorthand tiny
              Example: neofetch uptime disk wm memory
              This can be used in bars and scripts like so:
              memory="$(neofetch memory)"; memory="${memory##*: }"
              For multiple outputs at once (each line of info in an array):
              IFS=$' ' read -d "" -ra info < <(neofetch memory uptime wm)
              info=("${info[@]##*: }")
              --disable infoname
              Allows you to disable an info line from appearing in the output. 'infoname' is the function
              name from the 'print_info()' function inside the config file.  For example: 'info  "Memory"
              memory' would be '--disable memory'
              NOTE: You can supply multiple args. eg. 'neofetch --disable cpu gpu'
       --package_managers on/off
              Hide/Show Package Manager names . (tiny, on, off)

Conclusion

To work on the command line, you’re going to need some basic knowledge of Unix/Linux commands. Still, with the right tools, such as Midnight Commander or Ranger, you can minimize the need for memorizing and typing cryptic commands. Another of the terminal’s limitations, that it only shows one app at a time, can be beaten by using Tmux, where you can literally fill your screen with a dozen simultaneously running apps (not that getting too many is a good idea, but you could do it). Lastly, we looked at commands used to manipulate files and directories manually from the command line.

In the next chapter, we’ll look at several dozen command-line programs that will solve many of your work needs. We’ll look at email clients, writing tools, a spreadsheet, and several web browsers, all running in text mode.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.140.185.170