@part(chapter4, root "Athena/athena.workstation.mss") @chapter(Files and Directories) If you are going to use the Athena system to do any substantial work, you are going to create and manipulate files. Writing a paper? You'll store it in a file. A program? A file. A @b(file) is simply a bunch of data associated with a name (the @i(filename)). Most of the things you do in Unix affect files or their contents. Even the commands you type are filenames. Actually, there are two main types of files, @b(simple files) and @b(directories). Simple files contain text. If you're writing a paper, the file contains English text; if you're writing a C program, it contains C language text. If you're compiling a program, the compiler creates a file containing @i[binary] text. Most of the time you will use a text editor such as @i[emacs] to create and edit simple files. @i[Directories] provide a means of organizing the simple files into meaningful groups. If you plan to write a bunch of papers during the term, you may want to keep them together in a directory called @i[Papers]. If you're into programming, you may want to store your programs in a directory called @i[Programs], and within that directory, store the C programs in a @b[subdirectory] called @i[C_progs], the Fortran programs in a subdirectory called @i[F_progs]. @section[Directories, Pathnames, and the Unix File System] The Unix file system is just a bunch of simple files organized into a @i[tree] of directories and subdirectories. Every directory and every file has a @b[pathname] that specifies its location within the file system tree. For instance, when you login to an Athena workstation, the system puts you into a @b[home directory] that has the @b[pathname] @i[/mit/username] (where @i[username] is your username). The home directory's name is @i[username]. It is a subdirectory of the directory @i[mit], which in turn is a subdirectory of the file system's @b[root directory]. The @i[root directory] is named @b[/] (slash). Schematically, the @i[/mit/username] pathname looks like this: @begin[verbatim] / (root directory) | | mit | | username @end[verbatim] And it's just one branch in a large tree that looks something like this: @begin(group) @begin(verbatim) / (root directory) | | --------------------------------------------------------- | | | | | | | | | | bin dev etc ... mit ... usr | | | | | | ------------ | ------------- | | | | | arp ... athena | athena ... beta | ------------------------------------------- | | | | | | | | username username2 course1 course2 @end(verbatim) @end(group) The diagram above is a gross simplification of the tree. Each of the @i[root level directories] (@i[bin], @i[etc], @i[usr]) have their own subdirectories and files, which in turn have their own subdirectories and files, and so on. Later in this chapter, the section entitled @i[File Organization: An Aside] briefly describes the contents of the system's more important directories. @section[Listing a Directory's Contents with the ls Command] The @i[ls] command lists the files contained in a directory. Suppose you are in your home directory. An @i[ls] command might yield something like the following: @begin[example] athena% @b[ls] Mail welcome athena% @end[example] These are two items that will be automatically placed in your locker. Actually, the directory contains other files, as you'll see in a minute. @section[The Dot Files .login and .cshrc] @i[Mail] and @i[welcome] aren't the only files that come with your home directory, but @i[ls] won't list the others because they are @i[dot files], files with names that are prefixed with a dot @b[.] (a period). Use the @b[-a] option of @i[ls] to list them (@i[a] for @i[a]ll files): @begin[example] @tabset[2.5inches] athena% @b[ls -a] . .cshrc .mh_profile .. .login Mail welcome @end[example] Here's a quick explanation about the dot files listed above: @begin[itemize] The file @b[.] is the current directory, in this case your home directory @i[/mit/username]. The file @b[..] is the current directory's parent directory, in this case your home directory's parent @i[/mit]. All Unix directories refer to themselves as @b[.] and to their parent directory as @b[..]. The @i[.login] and @i[.cshrc] files are the @i[initialization files]. They help establish your working environment at login time. For more information, see the document @p[More Unix: the C Shell]. The @i[.mh_profile] file sets the proper environment for electronic mail. For more information about this file, see the document @i[Essential Messages]. @end[itemize] @section(Naming Directories and Files, Filename Extensions) Directory and filenames can be up to 256 characters in length, for what it's worth. You can use any character on the keyboard in a filename except a slash (/), but it is best to stick to a-z, A-Z, 0-9, the period or ``dot'' (.), and the underscore (_). If you use any other characters, you may be setting yourself up for serious trouble. Case matters in filenames: @i(myfile) is a different file from @i(Myfile). Unix filenames often have @i(extensions). For example, in a file named @i(foo.txt), the ``@i(.txt)'' is the extension. Files have extensions for two reasons. First, because an extension tells people something about a file; for example, a @i(.h) file is a program header file, and a @i(.mss) file is a @i(scribe manuscript) file. Second, because some Unix programs require that the files they deal with have a certain extension; for example, the C compiler requires that its source files have a @i(.c) extension. @section(Wildcards) Unix provides a mechanism called @i(wildcard characters) that lets you refer to more than one file at once. Here are the two most commonly used wildcard characters: @begin(description) @b(*)@\Matches all files except dot files. It can also match characters within a filename. For example, @i(*.f) means ``all filenames with a @i(.f) extension''; @i(h.f) and @i(verylongfilename.f) would both match. @i(a*) means ``all filenames that begin with @i(a)''; @i(a) and @i(anotherfilename) would both match. @b(?)@\Matches single characters. @i(?.f) means ``all one character filenames with a @i(.f) extension''; @i(a.f) would match but @i(ab.f) would not. @end(description) @section(Working With Files) The following commands let you list, examine, create, delete, copy, and rename files. @subsection(Other Options to the ls Command) The @i(ls) command has many options. To see them all, use the @i(man) command to look at the online manual page for @i(ls) by typing @b(man ls). Here are some of the more useful ones. @b(-l for Long) To get a list of your files that shows more information about them, type @b(ls -l). @example[ % @b(ls -l) total 2 -rw-r--r-- 1 @i[username] 1081 Jul 30 17:00 welcome % ] The first item on the line is the file's @i(mode). A ``d'' in the mode's first column means that the file is a directory. The r's, x's, and w's in the mode show who has permission to read, write, delete, and execute the file. The second item on the line is the number of @i(links) the file has. We won't explain links here, but for directories, it shows how many subdirectories exist beneath the file; there are always at least two. The third item is the username of the user who owns the file. In most cases this is your username. The fourth item is the size of the file in bytes. For a text file, this is the number of characters in the file. The fifth item is the date and time when the file was last modified. If a file has never been modified, it shows the date it was created. The sixth and final item is the filename. @b(-F for Type) As we said before, there are different @i(types) of files: simple files, which can be @i(text files), @i(binary files), or @i(shell scripts); and directory files. Often you need to know the type of the files you're listing. The @i(-F) option does this: @example[ % @b(ls -F) Mail/ a.out* myfortpgm.f welcome % ] Notice the suffix characters (/ and *) following some of the filenames. These characters are NOT part of the filename. The / suffix means that the file is a @i(directory file). The * suffix means that the file is a @i(binary file) or a @i(shell script). No suffix means either that the file is a text file or Unix cannot recognize its type. You can combine @i(ls) options to use more than one at the same time. For example, to get a @i(long listing) of @i(all the files) in a directory, type @b(ls -@p(la)). @subsection(Seeing the Contents of a File) There are two commands that display the contents of a file: @i(cat) and @i(more). Although the @i(cat) command is simpler, most people prefer the @i(more) command. @b(cat) The @i(cat) command (for @b(cat)enate) displays the contents of a file on the screen. Its command format is @b(cat @p(filename)). If the file is very long, its contents will scroll past you faster than you can read them. You can type @b(Ctrl-s) to stop the screen from scrolling and @b(Ctrl-q) to resume scrolling. However, if you have to do this, you should probably be using the @b(more) command, which doesn't let this happen. To cancel a @i(cat) command and stop its output, type @b(Ctrl-c). NOTE: The workstation may print out garbage and beep a lot after you ask it to ``cat'' certain files. This is because some kinds of files are unprintable; they contain data in a format that cannot be displayed on the screen. Binary files (the ones @i(ls -F) shows with a * suffix) are not printable; neither are directory files (the ones @i(ls -F) shows with a / suffix). @b(more) The @i(more) command displays a file's contents one screen at a time, pausing after every screenful so that you can read them. Its command format is @b(more @p[filename]). Once @i(more) has filled up the screen, you must give it a @i(subcommand) to tell it to continue. There are many such subcommands. Here are the most commonly used ones: @begin(group) @begin(description) @b(SPACEBAR)@\Move forward one screenful @b(RETURN)@\Move forward one line @b(b)@\Move back one page @p(/word)@b(RETURN)@\Search forward for @p(word) @b(q) or @b(Ctrl-C)@\Quit @end(description) @end(group) @i(More) is clever enough not to display undisplayable files. @i(More) is what is called a Unix @i(filter), that is, many other Unix commands filter their output through @i(more): instead of giving you their output directly, they send it through @i(more) so that it will be easy to read and under your control. In Unix parlance, we say that they ``@i(pipe) their output through @i(more).'' The @i(man) command that displays online documentation does this. You, too, can ``pipe things through @i(more).'' Whenever you enter a command and its output is too large to fit on one screen, cancel it by typing @b(Ctrl-c) and re-enter it like this: @example[athena% @b[@p(command) | more]] The ``|'' is the @i(pipe) character. For example, if you have collected hundreds of files, you can pipe the output of @i(ls) through @i(more) by typing @b(ls -l | more). Type @b(man more) to learn more about @i(more). @subsection(Creating a File) There are many ways to create a file. The usual way to do so is with the @i(emacs) text editor. See the Athena document @p(Essential Emacs) for more information. A quick and easy way to create a file is with the @i(cat) command. It works as follows: @example[ athena% @b(cat > easyfile) Unix moves the cursor down to the next line. Start typing. You can fix typing mistakes in the current line with the DELETE key. You can erase the current line by typing Ctrl-u. You cannot change previous lines. When you are done, finish the last line with a RETURN and then type Ctrl-d. It echoes as ^D. ^D athena% ] The > in the command line is the Unix @i(redirection mechanism). It tells the @i(cat) command to @i(redirect) its output somewhere other than the screen (in this case, into @i(easyfile)). With no arguments, the @i(cat) command simply echoes what you type, so it's literally echoing your input into a file. Be sure the arrow is pointing the right way. It is all right to have a blank between the > and the filename. You can redirect the output of any Unix command into a file. For example, you can put a listing of your files into a file so you can print it out and refer to it at your leisure: @example[ athena% @b(ls -l >mylisting) athena% @b(ls) easyfile mylisting welcome ] @subsection(Deleting a File with the rm Command) It is a good idea to delete files that you know you won't need anymore. Otherwise, your directory can become very full. The command to delete a file is @i(rm) (for @b(r)e@b(m)ove). Its command format is @b(rm @p(filename)). Unix doesn't verify the deletion; it just prompts for the next command. You can put more than one filename on the command line. You can use wildcards (with caution!) to delete groups of files. The most catastrophic mistake you can make is to type @b(rm *), which deletes @i(all) the files in the current working directory. Or worse yet @b[rm -r *]. @b[Note:] It is a @b[very] good idea to use @b[rm -i] to delete files. The @i[-i] option stands for @i[interactive], which will ask you to confirm the deletion you are performing. For example: @example[ athena% @b[rm -i myfile.txt] rm: remove myfile.txt? @b[n] athena% @b[rm -i yourfile.txt] rm: remove yourfile.txt? @b[y] athena%] @subsection(Moving or Renaming a File with the mv Command) To move or rename a file, use the @i(mv) command. Its command format is @b(mv @p[fromfile] @p[tofile]). Unix renames @p(fromfile) as @p(tofile), in effect moving it from one file to another. If @p(tofile) already exists, it is overwritten. As ever, Unix does not verify that it has moved the file. @subsection(Copying a File with the cp Command) The @i(cp) command copies a file. Its command format is @b(cp @p[fromfile] @p[tofile]). Unix makes a copy of @p(fromfile) called @p(tofile). If @p(tofile) already exists, it is overwritten. Again, Unix does not verify the copy. @subsection(The -r Recursive Option) Many commands have a @i(-r) or @i(-R) @i(recursive) option. When referring to directories, recursive means ``do it to this directory and to all the files and subdirectories underneath it.'' Recursive options are thus very powerful. For example, you can copy an entire subtree into your home directory by typing: @begin[example] athena% @b(cp -r /foo/bar ~@p[username]) @end[example] The @i(rm) command has a recursive option which makes it dangerously easy to delete an entire subtree. The @i(rmdir) command does not have a recursive option. @section[The Current Working Directory] Your @i[current working directory] is the directory you are ``in'' at any particular time. From the time you login to the time you logout, you are in a current working directory. You start out in your home directory because that is where the @i[login] process puts you when it gives you control of the workstation. @subsection[The pwd Command] The @i[pwd] command displays the pathname of your current working directory (@i[pwd] stands for @b[p]rint @b[w]orking @b[d]irectory). If you use the command immediately after logging in, the transaction will proceed as follows: @begin[example] athena% @b[pwd] /mit/@i(username) athena% @end[example] where @i[username] is @u[your] username. @subsection[Changing Directories with the cd Command] The @i[cd] command stands for @i(@b[c]hange working @b[d]irectories). Suppose you want to change your working directory from your home directory to the directory above it, @i[mit] (@i[mit] is your home directory's @i[parent]). Enter the following commands: @begin[example] @tabset[2.5inch] athena% @b[pwd] /mit/@i[username] athena% @b[cd /mit]@\@p[<-- Change working directory.] athena% @b[pwd]@\@p[<-- Print new directory's path.] /mit athena% @b[ls]@\@p[<-- List its contents.] @i[username] athena% @b[cd /mit/@p(username)]@\@p[<-- Change back.] athena% @b[ls] Mail welcome @end[example] If you are in a directory other than your home directory, you can use @i[cd] without an argument to change the working directory back to your home directory: @begin[example] @tabset[2.5inch] athena% @b[pwd] /mit/@i(username) athena% @b[cd /mit] athena% @b[pwd] /mit athena% @b[cd]@\@p[<-- Change back to home directory.] athena% @b[pwd] /mit/@i(username) athena% @end[example] If you don't specify a directory when using @i[cd], the command will always return you to your home directory. @section[Creating Directories] You use the @i[mkdir] command to create directories. Suppose you are in your home directory and you want to create a series of directories in which to store your programs. You want a directory called @i[Programs] with the subdirectories @i[C_progs] and @i[F_progs]. The following series of commands does the job and checks it along the way: @begin[example] @tabset[2.5inch] athena% @b[pwd] /mit/@i[username]@\@p[<-- From your home directory . . .] athena% @b[mkdir Programs]@\@p[<-- Make the subdirectory.] athena% @b[cd Programs] athena% @b[pwd] /mit/@i(username)/Programs@\@p[<-- From Programs directory . . .] athena% @b[mkdir C_progs]@\@p[<-- Make C_progs subdirectory,] athena% @b[ls] C_progs athena% @b[mkdir F_progs]@\@p[<-- and F_progs subdirectory.] athena% @b[ls] C_progs F_progs athena% @b[cd]@\@p[<-- change back to your home directory.] athena% @b[pwd] /mit/@i[username] @end[example] @section[Removing Subdirectories] If you want to remove a directory, you will use one of two commands: @b[rmdir], or @b[rm -ir]. The @i[rmdir] command removes @b[empty] directories, and @i[only] empty directories. If a directory isn't empty, @i[rmdir] will display an error message. You must then @i[cd] to that directory and remove all of its files and subdirectories. The @i[rm -ir] command (actually it's the @i[rm] command with the @i[-r] option and with the @i[-i] option) @i[recursively] removes directory contents--its files and subdirectories--then the directory itself. If any of the directory's subdirectories have contents, those are removed before the subdirectory. @i[rm -r] is a powerful, and hence, @b[dangerous] command. Make sure you know what you're doing when you use it; the @i[-i] option is a helpful safety. The following session illustrates the use of both commands: @begin[example] @tabset[2.5inches] athena% @b[pwd]@\@p[<-- From your home directory . . .] /mit/@i[username] athena% @b[rmdir Programs]@\@p[<-- Try to remove the Programs directory.] rmdir: Programs: Directory not empty athena% @b[cd Programs] athena% @b[ls]@\@p[<-- cd to Programs and see what's there.] C_progs F_progs athena% @b[ls F_progs]@\@p[<-- What's in F_progs? Nothing.] athena% @b[rmdir F_progs]@\@p[<-- You can rmdir to remove F_progs.] athena% @b[cd] athena% @b[rmdir Programs]@\@p[<-- cd to home and try to remove Programs.] rmdir: Programs: Directory not empty athena% @b[ls Programs]@\@p[<-- It's still not empty.] C_progs athena% @b[rm -r Programs]@\@p[<-- All right, let's quit goofing around.] athena% @b[ls Programs] Programs not found@\@p[<-- It's gone now.] athena% @end[example] Use @i[rmdir] and @i[rm -r] judiciously. It's an old Unix adage that says @b[@p(rm) is forever]. @section[Directory Abbreviations] With the exception of the @i[root directory] @b[/], all directories have a parent directory. Unix provides an abbreviation for a directory's parent; it's the @b[..] directory. Here's another example: @begin[example] @tabset[2.5inch] athena% @b[pwd]@\@p[<-- From your home directory . . .] /mit/@i[username] athena% @b[cd ..]@\@p[<-- cd to its parent directory.] athena% @b[pwd] /mit athena% @b[cd ..]@\@p[<-- Now cd to mit's parent,] athena% @b[pwd] /@\@p[<-- which happens to be the root directory.] athena% @b[cd]@\@p[<-- Then cd back to your home directory.] athena% @b[pwd] /mit/@i[username] @end[example] @subsection[The Directory ~ . . .] Is an abbreviation for your home directory. In other words, @b[cd ~] is equivalent to @b[cd]. Another for-instance: @begin[example] @tabset[2.5inch] athena% @b[pwd] /mit/@i[username] athena% @b[cd /etc]@\@p[<-- From your home directory . . .] athena% @b[pwd]@\@p[<-- cd to the root-level directory etc.] /etc athena% @b[cd ~/Programs]@\@p[<-- Now back to your subdirectory Programs] athena% @b[pwd] /mit/@i[username]/Programs @end[example] @section[Your File System Locker] Most of the time, when you login to a public workstation, that workstation creates your home directory and @i[attaches] your locker to it. Your locker is your home directory, and when you use the @i[ls] command to list its contents, you're listing a directory that is ``somewhere on the network'' on your file server machine. If your file server machine is down or unreachable when you try to login, the workstation will be unable to @i[attach] your locker. When this happens, the @i[login] process displays the following message: @begin[example] Warning: Unable to attach home directory. NOTE -- Your home directory is temporary. It will be deleted when this workstation deactivates. Your home directory cannot be attached right now. You may use a temporary directory, but **** WARNING **** If you do, any files you make or any mail you incorporate will be deleted when you logout and lost forever. Would you like to continue this login session, using a TEMPORARY directory? (yes,no) [The default is no] @end[example] And of course you don't have access to your permanent home directory. Press @b[Return] or @b[Enter] to halt the @i[login] process, and try logging in later. What happens if the file server becomes unreachable while you're in the middle of a login session? You temporarily lose access to your files. @b[You don't lose anything permanently.] You can tell that the file server is gone if you use any of the directory commands while in your home directory or any of its subdirectories. Suppose you're in your home directory and you try to use @i[ls]. If something is wrong, your workstation will begin displaying @b[black bar] messages that say something like this: @begin[example] athena% @b[ls] NFS getattr failed for server @p[server]: TIMED OUT @end[example] This message may appear a thousand times while you watch in disbelief. If you stay logged in and wait long enough, your files will reappear when the network heals. If you get tired of waiting, make sure you logout. Otherwise the next person who uses the workstation will have access to your files when the network comes back. @subsection[But I'm in the Middle of an Emacs Session!] Don't panic. Use the @i[emacs] command @b[Ctrl-x Ctrl-w], and write the file in the directory @b[/usr/tmp]. The file will stay in that directory on that particular workstation for four days, so you have ample time to move it to your locker when the network comes back. @section(File Organization: An Aside) @label(aside) This chapter has mainly talked about your own files. But, as anyone new to Boston must, over time, construct a mental map of the city, its suburbs, squares, T stops, restaurants, movie theatres, and points of personal interest beyond their immediate neighborhood, so should you get an inkling of what is kept in other parts of the Unix file system. Here's a brief tour. Type @b(ls -F /). You will see something like: @example[ bin/ flp0/ mnt/ ultrixboot boot* flp1/ site/ urvd/ bootblock lib/ srvd/ usr/ dev/ lost+found/ stf/ vmb.exe* etc/ mit/ tmp/ vmunix* ] Each of these @i(root level directories) (the ones followed by a /) contains different sorts of files that Unix needs in order to function. There are strong historical conventions for what is kept in each of them (as well as many arbitrary exceptions). You can look at most of the files in each of these directories. With a few exceptions, Unix is open for inspection by anyone curious enough to look. Here is a short description of what's kept in some of these directories: The @i(/bin) directory contains the binary (unreadable, executable machine language) versions of the programs you absolutely can't bring up Unix without, such as the @i(cat) and @i(rm) commands. When you type the @i(cat) command, you are actually executing the file @i(/bin/cat) in this directory. The @i(/etc) directory contains all the administrative information files necessary to run the system. This includes the @i(/etc/passwd) file that defines who has a username on the system. It makes for interesting browsing. The @i(/mit) directory, as you already know, contains your files and the remote software packs. Perhaps the most interesting directory is @i(/usr). @i(/usr) has traditionally been where users' files were kept. (Athena uses @i(/mit) for this.) Later, it also came to be the place where documentation, games, and programs added at the local site were kept. For example, @i(/usr/ucb) has all the programs that the University of California at Berkeley added to the original Unix to make Berkeley 4.0. @i(/usr/athena) has all the programs, like Scribe and Emacs, that Athena is adding to the Unix it got from Berkeley. The @i(/usr) directory is worth quite a bit of browsing. The @i[Student Information Processing Board] (@i[sipb]) maintains a file system full of interesting software packages that you can @i[attach] to your workstation after you have logged in. After you have @i[attached] this file system to your workstation, you can @i[cd] to the @i[/usr/sipb] directory and look around. See Section 3 of Appendix B for more information about @i[attaching] the @i[sipb] file system.