If you're one of the many people who are new to Linux or one of the ``Freenix's,'' you probably could use some help with being efficient at the Bash command line. While several good books exist, you may want some something small that you can use today. So, here we go.
The default command shell on every Linux system I've ever installed has been BASH, short for the Bourne Again SHell, which is a highly improved Bourne Shell, the original command shell on UNIX SysV systems. And, Bash is GNU software, so it's free.
The shell is an interpreted language, meaning that you don't compile it. You write a collection of instructions and the interpreter executes them line by line. A compiled language requires that you place the instructions into a source file, then compile them into a binary executable. Shell scripts are examples of the former rather than the latter. (Note: nowadays, this distinction isn't as easy to make, because there are compiled scripting languages as well, but generally speaking, Bash and other scripting languages are interpreted rather than compiled languages.)
Interactive Execution and Scripting. Sometimes, you just want to do a one-time, small scale job and won't need to repeat this procedure, so you may not want to write an executable script. You may need something more than a one-liner, but not enough more to justify a full-blown shell script. For example, let's say you just discovered that UNIX is spelled in all caps, and you want to search a directory full of text files for the other variations of the term that you want to correct. You could type the following from the commandline:
for file in * >do >if grep -l Unix $file || grep -l unix $file; >then >sed -e 's/unix/UNIX/g; s/Unix/UNIX/g' > $file.new >mv $file.new $file >echo "$file has been corrected" >else echo "$file needs no correction" >fi >done
grep is a UNIX way of saying ``find''; the funny name probably comes from a command in the ed editor: g/re/p, meaning global regular expression print. I like to liken ``grepping'' to ``groping,'' and that makes my work a lot more fun! sed is a popular stream editor on UNIX systems, so the fifth line simply replaces the misspelled words in the files already specified by grep.
Whenever you type Bash commands on the commandline that the interpreter
recognizes cannot be completed without further arguments, Bash will give
you another prompt called ``$PS2''. (The value of $PS1 is what you
see at the commandline the rest of the time, usually something like
[you@hostname]$ .) (The dollar sign is the important
ingredient in the $PS1 values.) This $PS2 prompt usually looks like
> . So, when you see a ``> '' at the commandline, Bash is
expecting you to type the rest of what you want it to do.
You can try this now. Create a temporary directory with three files in it. In one file, include the line, I use Windows., in another file the line, I use unix., in another file the line, I use Unix.. Change to this temporary directory and at your Bash prompt, type the above instructions (the instructions beginning with for file in *) at the commandline. (Bash will supply the >.) Let the instructions be executed on each of the files in your temporary directory. Then type more * and you'll see that the two files that had ``Unix'' and ``unix'' now each have ``UNIX'' in them instead. The file that had ``Windows'' isn't changed.
Making Executable Scripts. You can accomplish the same thing by writing a shell script if you think you'll need to reuse the instructions. This is actually a shell program that you can execute by typing its name at the commandline. But to do so, at the top of the executable file you must place a ``magic line'': #!/bin/bash or #!/usr/local/bin/bash, depending on where Bash resides on your system.
Now, if you wanted to make a script out of the above instructions, you could type the following into a file, put it in your path (perhaps /usr/local/bin or $HOME/bin) and make it executable:
#!/bin/bash for file in * do if grep -l Unix $file || grep -l unix $file then sed -e 's/Unix/UNIX/g; s/unix/UNIX/g;' $file > $file.new mv $file.new $file echo "$file has been corrected" else echo "$file needs no correction" fi done exit 0
Once you create this shell script and save it as an executable program, you can use it as often as you want. Note: most Bash scripts use a #!/bin/sh magic line, because many systems have either Bash or the Bourne shell in place. If Bash is installed, many times /bin/sh is a symlink to /bin/bash, or some similar Bash installation. Consequently, try to write scripts that are simple enough to be compatible with both /bin/sh and /bin/bash, and use #!/bin/sh as your magic line.
Also, the permissions of this script must allow execution by everyone you want to execute it. You can see if your script is executable by typing ls -l pathto/scriptname at the commandline. The script may be executed by everyone whose group has an ``x'' in the permissions summary. So, if the permissions summary says -rwxrwxr-, then it may be executed by the owner, the group, but not the rest of the world. (See man chmod for a better explanation of UNIX permissions. Better yet, see Sections 3 and 4 of the DOS/Win to Linux HOWTO.)
Making your script executable calls for a chmod ugo+x filename command, where ``filename'' is the path to and name of the script. ``ugo'' means ``user'', ``group'', and ``others'', so you are giving execute permissions (+x) to everyone by doing this. If you just want your group to execute it, try chmod ug+x filename.
Paths. I've mentioned ``paths'' and ``pathnames'' above, just as if you knew exactly what I was talking about. In the event you don't, here's a brief explanation.
Since UNIX systems can be large and complicated, Bash doesn't like to waste time looking for things that aren't where they're supposed to be. If you create a script in /home/myname/myscriptname and you haven't told Bash to execute it in that directory, your script will not be found. For example, if you type myscriptname in your home directory, even after making it executable as described above, unless Bash knows to look for executable programs in /home/myname, you'll get an error: bash: myscriptname: command not found.
There are several fixes you can make. You can use the ./myscript notation when you issue the command that tells Bash that myscript is in the current directory, assuming it is in the current directory. You can also type the complete pathname to myscript at the commandline. (Example: $ /home/myname/myscriptname [arguments]) Or you could include /home/myname/myscriptname in your $PATH variable.
The $PATH variable is set either from the /etc/profile or $HOME/.bash_profile files. You can see what is in your path right now by typing $ echo $PATH at your commandline. You'll probably see something like /usr/local/bin:/usr/bin:/usr/bin/X11. You can add to the default $PATH value from /etc/profile by making adding something like PATH=$PATH:/home/myname/bin to your $HOME/.bash_profile file.
Most often, you can just use the ./myscript approach until you get your script working just as you want, then move it to a location in your $PATH.
In future articles, I'll discuss some other aspects of your powerful Bash command interpreter.