What and where did Bash start?
Bash, which is short for Bourne-again shell, is a very popular interactive command line interpreter, or shell. It has a very long history, starting with the first Unix shell, which was called the Thompson shell, in 1971. The Thompson shell was very minimalistic and it lacked a lot of important features. And it was replaced in 1975 by the Mashey shell. That in turn was replaced in 1977 by the Bourne shell, named for Stephen Bourne, which had many of the features we still use, like command substitution, various types of loop constructs. And some commands that you're probably familiar with. Like cd, pwd, and export.
Break and continue, getopts ans some others. Some of these were brought in from other projects like ALGOL. However, it was criticized for not being as friendly to use as the C shell, which was introduced in 1978, and had a style more similar to the C language. The Bourne shell on the other hand looks more similar to ALGOL. C shell predated TC shell, which is the default login shell on Mac OS 10 before 10.3 and is still the default shell in FreeBSD. And it kicked off some other variants as well, such as KornShell, or K Shell, which is the default script shell in OpenSolaris.
These shells and others owe a lot of their heritage to the Bourne shell and have evolved to have different feature sets and to live on different platforms. In 1989, Bash was released as a free alternative to the Bourne shell under the GNU project which promotes the freedom of users to run, share, study, and modify software. Brian Fox, the original author maintained Bash until 1994, when Chet Ramey took over that responsibility. Bash is the default shell on Mac OS 10 and Linux, making it incredibly widespread. As of this recording, the current version of Bash is 4.2, which was released in February of 2011.
Currently Mac OS 10 ships with an older version of Bash, 3.2. And the installed version on different Linux distributions can vary slightly. You can find more information about the Bash project at Chet Ramey's website here. Bash brings to the table some other built-ins, which make building scripts a lot easier. Echo, printf, and read, along with some others that you'll see like declare and some of the ones I won't cover here but are very handy, like bind and alias. In addition to these built-ins, Bash provides some very useful features like expansions, shell arithmetic, and the extended test construct which you'll see later on.
You may or may not be use to working at the command line. If you are not, that's fine. In this movie, I'll provide a quick look at some of the common commands that you'll use. First, it's important to understand how to move around the directory structure. Typing pwd, prints the working directory. That is, it tells you where you currently are, the active working directory. What that means, is if you run a command, this is where the system will execute it. If you say, delete all the files here, it'll delete all the files in this current working directory. And you can see I'm in my home directory, which is where my personal files live. Yours will be different unless you're named Scott, and you're using a Linux machine.
On Macs, your home folder will be inside the slash users folder at the root of the drive, and on Linux, it'll be in slash home. You can check out what's in a directory with the LS command, which lists the files and folders in the current working directory. Here I've got some folders called Trees, Fruit and Pets. To see what's in one of those folders, I can use the LS command, followed by a space and the name of that folder. And I can ask LS to show me the difference between files and folders, using the dash L option. So here I can see I have a directory called Cedar, and I know it's a directory, because it has a D at the beginning of this line here.
Then I have a file called maple.txt, and there's no indication that it's a directory. Then a directory called pine, and a file called pine. A directory called spruce, a directory called sycamore, and a file called tree.png. There's a whole lot of other stuff here,rwx, rwx, rwx. Those are the permissions for the file. And we don't have time to get into that now, but I encourage you to check out Kevin Skoglund's course, Unix for Mac OS X Users, to understand more about permissions and ownership, and groups.
There's all kinds of options that you can use with LS and you can look those up using the MAN command, MAN LS. What MAN does, is show you what are called the manual pages, and they provide a comprehensive guide to almost any command that you can think of. You just press the Spacebar to page through. If you're feeling adventurous, you can press H, which brings up the reference for navigating around. And when you're done, just press Q. So I can create a directory or folder using mkdir, for make directory. I'll make one called People.
And I can check that out. And here it is, directory People. And of course I can delete a directory with rmdir. So let's get rid of that people directory. Now we'll use the CLEAR command here, just to clear the screen. Everything that I've done isn't gone, it's just in the scroll back up here, but it makes my terminal window a little nicer to look at. So, let's move into that Trees directory. To do that, I'll use the CD command to change directory. And I can run LS and see the files in this directory. I can make a copy of the file with the CP command, followed first by the file I want to copy, and then the name of the file I want to copy it to.
In this case, I've copied maple.txt to new_maple.txt. And here it is. Of course I can remove the file with the rm command. And as you can see, it's been deleted. I'll clear the screen again. In the last set of commands that I want to show you in this quick introduction, let you see what's in a file. Let's take a look at what's inside of the pine.txt file with the cat command. Cat has some other functionality. It's designed both to concatenate or stick files together, and to print their contents to the screen.
Line by line and dumps out everything. Keep in mind that what you see will only make sense if the file is a text file. If it's a binary file, like an image or an executable, for example, the file tree.png, you'll get what looks like a whole bunch of gibberish. Those noises heard weren't an error, they're actually a character called bell. And I'll clear the screen again. You can use the more command to paginate a long file. That is, to pause printing out of the file page by page so you can read it a little easier.
And here you can press Spacebar to move through the pages. And then Q when you're done. You can also peek at the beginning of a file with head. And that just shows you the first couple lines, make some space here. You can also look at the end of the file with tail. This shows you the last couple of lines of the file. This is really handy for log files. So, there's hundreds of commands that you can use at the dash prompt. And for more detail on these and others, I encourage you to check out Kevin Skoglund's course here on lynda.com called Unix for Mac OS X Users. The first eight chapters cover bash commands that are relevant to both Mac users and Linux users.
Bash provides some handy shortcuts called expansions. And you may already be familiar with one of them even if you don't know what it's called. If you've ever used the tilde character to represent your home directory you've used tilde expansion. The tilde character represents the value of the user's home variable. The tilde followed by a dash or a minus represents the batch variable called old PWD, which is the directory that you were just in, if you've recently changed directories. There's some other features as well and I encourage you to check out the documentation on tilde expansion to learn more. I'll step into the fruit directory here.
Another handy type of expansion is called brace expansion. This is written with braces around an expression, and it can help with repeated commands with different terms or interpolation within a range. Let's say I wanted to create a bunch of files, but I didn't want to type each command to do so. With brace expansion, I can type touch apple, banana, cherry, durian. And I could see that that created four files. Of course, I could do that with touch just by itself, but I can use interpolation for things that I really don't want to type out each time. Let's say I want to create a thousand files.
It would be a little tedious to touch each of those individually, so I can type touch, and then the beginning of the file name, file_, this can be whatever you want, 1..1000. And close the brace. And then when I list the directory, there's a thousand new files. Now, the upper limit of this range seems to vary by platform. On my Mac, I can get up to about 14,340. My Linux machine here goes much higher than that. But, that's not really the point. Bash version four added the ability to pad theses series of numbers with zero.
Normally if I asked for the numbers one through ten, I'd get this. But if I started naming files like this they wouldn't sort the way you might want, as you saw before. For example, file_428, file_429, file_43, file_430. Of course, that's not an incorrect sort. There is a logic to it. But like I said it may not be what you expect. I can fix that with zero padding but first let me clear out all these files and I'll create new files. Notice the zero in front of the one, it doesn't matter how many places you need to pad, one zero is all it takes.
So now the files sort the way I'd expect and they all have the same file name length. As of Bash 4, you can also specify an interval. I'll clear the screen here and then I'll type echo and {1..10..2}. In this case, I'll get the numbers between one and ten counting by twos or threes or any absolute value integer you might need. Brace expansion works with letters as well. As you can see, the capital letters come before the lower case letters, with a couple of symbols in between.
And like I mentioned, with Bash 4 and above, you can specify an interval with letters as well. Brace expansion will interpret the range that you give it, so as an example, I said w..d, which is not only backwards, but it's also a subrange of the alphabet. If you do use this in your scripts, make sure to keep in mind that your target audience may not have this feature available if they're on certain platforms. And I can chain together these expressions as well. I'll get rid of all those files I created just a minute ago. And type clear to clear up the screen.
And then I'll create a series of files, named with a fruit, underscore, a number, underscore, and a lower case letter. And suddenly I have thousands of files. In fact, I can take the output of ls -1. And pipe it into wc -l, which is a word count, with the -l flag giving me the line count. And I can see I have 8000 files. Obviously, this has applications beyond file creation, and it's important to be able to recognize when it's being used and when to use it.
A lot of what you'll be doing with scripts involves getting something to go somewhere else. Bash has a couple ways of doing this. First, let's look at pipes. Piping takes the result of one command and sends, or pipes it into another command. For example, take a look at the result of listing the contents of this directory, which has a lot of things in it from the previous movie. That's a bunch of stuff. It would be nice to take that output, and display it page by page. I can do this by piping the output of ls into the more command. And if you're looking for the pipe character, it's usually Shift Backslash. The key for which on most keyboards is right above the Return key, but your keyboard might vary.
And now I can take advantage of more's pagination. Redirection, on the other hand, works with a standard input, standard output and standard error. That is, the input from the command line environment, the output to it and the errors that arise when something goes wrong. Let's set up a little bit of an example here. First, I'll make another folder to copy to. And, I'll make it so that I don't have access to read some of the files in this current folder. This will cause some errors later on, and that's what I want. So, I'll copy these files into the other folder.
The v here tells the cp command to be verbose, so we see each copy operation. And I'm specifying star, to use file name expansion to match all of the files. Then I'm using the two dots and the slash in the destination path to indicate that other folder is a child of this folder's parent folder. That is, the cp command will have to go up a folder level to find other folder. And if I scroll up here. There's some errors. I couldn't copy some files, the ones named with a 015, which you remember I blocked everyone from reading.
And the other files copied just fine. So, I'll clear the screen. I'll get rid of everything in that other folder. I'll write another command here, and I'll explain it in just a minute. These numbers, one and two, represent the standard output and standard error, respectively. The greater than symbol represents redirecting the output from each of those somewhere else. So the successes will go to a file called success.txt. And the errors will go into a file called error.txt.
I'm putting them one level up. So if I want to run this command again, I won't be copying my success and error files into the other folder. And that time there was no feedback. That's because I redirected both the regular messages that would normally appear at the standard output, and the errors to text files instead. This can be pretty handy if you want capture the output of commands you're running. I'll type cat ../success,txt, and then cat ../error.txt. Cool.
I'll clear out that folder again. You can also tell bash to redirect standard output and standard error to the same place. Here using the ampersand to represent both one and two. And I can see that everything's there. You can also redirect to a special location called dev null if you just want to get rid of and ignore an output from a command. For example, I could redirect the output of ls to dev null. And the results just go off into the great blue nowhere, never to be seen again.