Mac OS X Unleashed

Mac OS X Unleashed

By John Ray and William C. Ray

Rearranging Files

If you're a long-time Macintosh user, you are probably familiar with the notion of moving files about by way of the Macintosh's drag-and-drop formalism. Unix and its command line might not seem like a particularly appealing way to deal with moving files—having to type the names and paths to directories can't possibly be much fun! There's no way to deny that there are certain tasks for which the drag-and-drop way works much better than the command line. But, although you might not have thought about it, there are also situations in which drag-and-drop makes your life much more difficult. Interestingly, these are frequently situations in which the command line works particularly well; for example, when a folder contains a great number of files of the same type and you're interested in using a number of them that are related by name rather than by icon position. In a situation like this, rearranging things in the Finder, or Shift- clicking your way through the list of files to pick the ones you want, is usually less efficient than choosing them from the command line by using a shell filename wildcard. Similarly, it's frequently faster to type a filename, if you know it, than to scroll around in a Finder window looking for the file. For these reasons, as well as conveniences that really become apparent only from experience rather than explanation, the command line makes for a useful complement to the Finder for certain operations.

Renaming Files: mv

Renaming files in Unix is accomplished with the mv (move) command. It might seem odd at first that renaming a file is accomplished by moving it, but it makes sense in the Unix sense of accomplishing things in simple, abstract ways. Why create two commands that do essentially the same thing, when one command can do both with the same syntax, the same way. To rename a file from one name to another, simply use mv <oldfilename> <newfilename> . For example, if you're in a directory with a file named mynewfile, and you'd like to rename it as myoldfile, you might do something like this:

[localhost:~/Documents] nermal% ls

     lynx       lynx.cfg   mynewfile  test

[localhost:~/Documents] nermal% mv mynewfile myoldfile

[localhost:~/Documents] nermal% ls

     lynx       lynx.cfg   myoldfile  test

Remember that most commands can take absolute paths or relative paths to files? Well, being in the same directory and using just the filenames is using the relative paths. On the other hand, you can accomplish the same thing using the absolute paths to the files like this:

[localhost:~/Documents] nermal% ls

     lynx       lynx.cfg   mynewfile  test

[localhost:~/Documents] nermal% pwd

     /Users/nermal/Documents
[localhost:~/Documents] nermal% mv /Users/nermal/Documents/mynewfile /Users/nermal

      ccc.gif
   /Documents/myoldfile
[localhost:~/Documents] nermal% ls

     lynx       lynx.cfg   myoldfile  test

Because you can do that, why should you need to be in the same directory as the files at all? As a matter of fact, because you can specify the full paths to the files, what is to stop you from changing something other than the filename when you use the mv command? What if you decide to change one of the directories in the full path while you're at it? For example, let's look at what happens if you move a file from the Documents directory at the same time that you change its name:

[localhost:~/Documents] nermal% cd ~
[localhost:~] nermal% ls

     Desktop                   Network Trash Folder      chown-output
     Documents                 Pictures                  myfile
     Library                   Public                    output-sample6
     Movies                    Sites                     su-output
     Music                     TheVolumeSettingsFolder   typescripts

[localhost:~] nermal% ls Documents

     lynx       lynx.cfg   mynewfile  test
[localhost:~] nermal% mv /Users/nermal/Documents/mynewfile /Users/nermal/Public/myoldfile
[localhost:~] nermal% ls Documents/

     lynx     lynx.cfg test

[localhost:~] nermal% ls Public/

     Drop Box   myoldfile

The end result is that Unix's abstraction of file access and naming causes the full path to the file to be, essentially, the full proper name of the file. "Renaming" it using the mv command can result in a change to any part of that name, including the parts that indicate the directory in which the file exists. See? Nothing odd about using the same syntax to rename files as used to move them about at all.

The command documentation table for mv is shown in Table 13.1.

Table 13.1. The Command Documentation Table for mv

mv Moves files.
mv [-fi] <source> <target>

mv [-fi] <source1> <source2> <source3> ... <directory>

            
In the first form, mv renames <source> to the name provided by <target> . If <source> is a file, a file is renamed. Likewise, if <source> is a directory, a directory is renamed.
In the second form, mv moves the list enumerated by <source1> <source2> <source3> ... to the directory named by <directory> .
-f Forces an existing file to be overwritten.
-i Invokes an interactive mode that prompts for a confirmation before overwriting an existing file.
The last of any -f or -i options determines the behavior of mv.

Creating Directories: mkdir

The mkdir command is used to create directories. The usual syntax is very simple, being most commonly used as

mkdir <new directory name>

This will create a new directory named <new directory name> in the current directory. Full and relative paths are allowed to the new directory being specified. If the path to the directory that you are attempting to create does not completely exist, mkdir will not create the entire directory structure. For example, if you want to create /usr/local/tmp/testing/morefiles/, and the directory /usr/local/tmp/testing/ does not exist, you will have to create it before you can create /usr/local/tmp/ testing/morefiles/. This holds for all levels in the directory hierarchy. The command reference is shown in Table 13.2.

Table 13.2. The Command Documentation Table for mkdir

mkdir Makes directories.
mkdir [-p] [-m <mode>] <dir1><dir2> ...
mkdir creates the named directories in the order specified, using mode rwxrwxrwx (0777) as modified by the current umask (2).
The user must have write permission in the parent directory.
-p Creates all nonexistent parent directories first. If this option is not specified, the full path prefix of each operand must already exist. Intermediate directories are created with permission bits rwxrwxrwx (0777) as modified by the current umask (2), plus write and execute permission for the owner.
-m <mode> Sets the permission bits of the created directory to <mode> . <mode> can be in any formats specified to the chmod (1) utility. If a symbolic mode is specified, the operation characters + and - are interpreted relative to an initial mode of a=rwx.

Copying Files: cp

The cp (copy) command functions in a similar fashion to the mv command, but instead of renaming a file between two locations, the cp command creates a duplicate of the file. The syntax is also similar, copying a file from one location to another or copying a number of files into a directory.

If our user nermal would like to copy some images to the /Users/shared directory so that all users can conveniently find the images without having to remember which user has the images, she can copy them with the cp command to the desired location.

Because nermal is new to Unix, she first decides to double-check that the images are located where she thinks they ought to be with the following:

[localhost:~] nermal% ls -l Public/Drop\ Box/shar*tiff

     -rw-r--r--  1 nermal  staff  872714 Apr 16 16:17 Public/Drop Box/sharing -1.tiff
     -rw-r--r--  1 nermal  staff  873174 Apr 16 16:17 Public/Drop Box/sharing -2.tiff

Then she actually copies them and verifies that they copied:

[localhost:~] nermal% cp Public/Drop\ Box/shar*tiff /Users/shared/

[localhost:~] nermal% ls -l /Users/shared

     total 3424
     -rw-r--r--  1 nermal  wheel  872714 Apr 23 11:08 sharing-1.tiff
     -rw-r--r--  1 nermal  wheel  873174 Apr 23 11:08 sharing-2.tiff

She could have copied each file individually, but cp can fortunately take multiple files in its arguments, so she can use shar*tiff to refer to both files. Note that the copies in the /Users/shared directory show the date that they were copied, rather than the original date. If everyone knows that the images from April 16 are the ones they need to use, they might be confused by the April 23 date. nermal could remove this confusion by specifying the -p option, which preserves as much as possible of the original modification time, user information, and so on:

[localhost:~] nermal% cp -p Public/Drop\ Box/shar*tiff /Users/shared/

[localhost:~] nermal% ls -l /Users/shared

     total 3424
     -rw-r--r--  1 nermal  staff  872714 Apr 16 16:17 sharing-1.tiff
     -rw-r--r--  1 nermal  staff  873174 Apr 16 16:17 sharing-2.tiff

Note the use of the \ character to escape the space in the folder named Drop Box so that the shell doesn't interpret Public/Drop as one argument and Box/shar*.tiff as another.

If user joray has promised nermal some test data in a subdirectory named tests-for-nermal in joray's home directory, nermal can recursively copy the test directory to her own home directory as follows:

[localhost:~] nermal% cp -R ~joray/tests-for-nermal ./

A check shows that a directory was indeed copied:

[localhost:~] nermal% ls -ld tests-for-nermal

     drwxr-xr-x  9 nermal  staff  262 Apr 23 11:29 tests-for-nermal

Not only that, but there was a directory under that directory, and cp copied it:

[localhost:~] nermal% ls -l tests-for-nermal

     total 48
     -rw-r--r--  1 nermal  staff   15 Apr 23 11:29 broken
     -rw-r--r--  1 nermal  staff   20 Apr 23 11:29 broken-again
     -rw-r--r--  1 nermal  staff   23 Apr 23 11:29 fix
     -rw-r--r--  1 nermal  staff   17 Apr 23 11:29 fix2
     -rw-r--r--  1 nermal  staff  848 Apr 23 11:29 test
     drwxr-xr-x  4 nermal  staff   92 Apr 23 11:29 test-data
     -rw-r--r--  1 nermal  staff  848 Apr 23 11:29 test2

You have seen just some of what you can do with cp. The complete syntax and options for cp are in Table 13.3, the command documentation table.

Table 13.3. The Command Documentation Table for cp

cp Copies files.
cp [-R (-H | -L | -P)] [-f | -i] [-p] <source>

                     ccc.gif
                   <target>

cp [-R (-H | -L | -P)] [-f | -i] [-p] <source1>

                     ccc.gif
                   <source2> ...

<directory>

            
In its first form, cp copies the contents of <source> to <target> .
In its second form, cp copies the contents of the list enumerated by <source1> <source2> ... to the directory named by <directory> . The names of the files themselves are not changed. If cp detects an attempt to copy to itself, that attempt fails.
-R If <source> is a directory, cp recursively copies the directory. This option also causes symbolic links to be copied, rather than indirected through. Created directories have the same mode as the corresponding source directory.
-H If -R is specified, symbolic links on the command line are followed, but symbolic links in the tree traversal are not.
-L If -R is specified, all symbolic links are followed.
-P If -R is specified, no symbolic links are followed.
-f Forces an existing file to be overwritten. If permissions do not allow the copy to succeed, this forces the existing file to be removed and a new file to be created, without prompting for confirmation. The -i option is ignored if the -f option is specified.
-i Invokes an interactive mode that prompts for a confirmation before overwriting an existing file.
-p Causes cp to retain as much of the modification time, access time, file flags, file mode, user ID, and group ID information as permissions allow.

Creating Symbolic Links: ln

Sometimes it is useful to be able to link a name with a particular file or directory. This can be done with the ln command. It is especially useful for administrative purposes, but even a regular user might have the need to link a filename or directory name to some other particular name. The best way to do this is to use a symbolic link. The simplest syntax for making a symbolic link is

ln -s <source> 
   <target>

Because the syntax is similar to the basic cp syntax, you won't have much trouble remembering it.

You might be wondering just what sort of use you might have for symbolic links. An instance in which you might use a symbolic link is for your Web site. Suppose that you are using a Web editing suite that uses home.html for the default name for the main page of your Web site. Suppose, however, that your Web server is set to read only files named index.html as the default page for a directory. If you use home.html, you might have to give out something like http://ryoohki.biosci.ohio-state.edu/~nermal/home.html as your URL. If, on the other hand, your home.html file were really called index.html, you could give out a slightly shorter URL instead: http://ryoohki.biosci.ohio-state.edu/~nermal/.

What could you do to get an index.html file in your directory if your Web editing suite won't create one? And how could you keep it conveniently updated to match home.html? Well, as you just saw, you could copy home.html to index.html. But the next time you edited home.html, you would then have to remember to copy home.html to index.html when you were done. Although you might be very good about remembering to do that, you undoubtedly will eventually forget, probably when it matters most. If you simply link index.html to home.html, every time you update home.html, you don't have to remember to do anything else! To create the symbolic link, do the following:

[localhost:~/public_html] nermal% ln -s home.html index.html

A quick check shows us that index.html is now a link to home.html.

[localhost:~/public_html] nermal% ls -l

     total 16
     -rw-r--r--  1 nermal  staff  52 Apr 23 11:56 home.html
     lrwxr-xr-x  1 nermal  staff   9 Apr 23 11:56 index.html -> home.html

A common administrative use for symbolic links is to move a directory from one partition to another, while leaving the path that a user would use to get to the directory the same. This makes the change that the administrator has made transparent to the user for most purposes. An example of this follows. On this machine, /usr partition was getting full, so the local directory of /usr/local was moved to the /home partition. After the directory was moved, the /usr/local directory was replaced with a symbolic link that points to /home/local.

Rosalyn joray 201 > ls -l /usr/local

     lrwxrwxrwx   1 root     other    11 Mar 20  1997 /usr/local -> /home/local

If a user changes to the /usr/local directory and then checks her location with pwd, she finds the following:

Rosalyn joray 202 > cd /usr/local

Rosalyn local 203 > pwd

     /home/local

So, as the user might have grown to expect, she can still cd to /usr/local, but without having to know any of the "administrivia" behind its actual location.

The complete syntax and options for ln are in Table 13.4, the command documentation table.

Table 13.4. The Command Documentation Table for ln

ln Makes links.
ln [-fhns] <source> <target>

ln [-fhns] <source1> <source2> <source3> ...
<directory>

            
In the first form, ln links <source> to <target> . If <target> is a directory, a link named <source> is placed in <target> .
In the second form, ln makes links to the files enumerated by <source1> <source2> <source3> ... in <directory> . The links have the same names as the sources in the list.
There are two types of links: hard links and symbolic links. The default is hard links. A hard link to a file is indistinguishable from the original directory entry. Hard links may not normally refer to directories and may not span file systems.
A symbolic link refers by name to the file to which it is linked. Symbolic links may refer to directories and may span file systems.
-f Forces the link to occur by unlinking any already existing links.
-h If <target> or <directory> is a symbolic link, it is not followed. This is most useful when used with -f, to replace a symbolic link that might point to a directory.
-n Same as -h. Retained for compatibility with other implementations of ln.
-s Creates a symbolic link--this is most like the idea of aliases with which you're already familiar.

Changing Modification Times, Creating Empty Files: touch

The touch command is used to update the last-modified time for a file. This command also has the side effect of creating a new, empty file, if the file that you attempt to touch does not exist.

Neither of these functionalities probably sounds particularly interesting at the outset, but, in fact, they both have good uses. For example, most archiving and backup software is frequently configured to back up only files that have changed since the last backup. Using touch on a file makes it appear to have been changed, which results in it being flagged for backup. Because the touch command can be quickly applied from the command line to a large number of files, it allows you to conveniently force some files to be backed up without having to open and resave each in its parent applications.

Creating empty files doesn't have much use at the command line, but turns out to be a very useful thing to be able to do when you start writing programs in the shell scripting language (Chapter 18 "Programming with the Shell: Shell Scripting"). In this case, multiple simultaneously running scripts can be made to talk to each other by the creation of empty files known as flag files—essentially the electronic ability for a script to raise a flag to tell another script that something has happened.

To create a new (empty) file with touch, or to update the modification date of the file to the current time, the syntax for the touch command is simply

touch <filename to modify>

The touch command can actually update files to have any modification time that you'd like, although the preceding is by far the most common usage. Table 13.5 shows the command documentation table for touch.

Table 13.5. The Command Documentation Table for touch

touch Changes file access and modification times.
touch [-acfhm] [-r <file>] [-t [[CC]YY]MMDDhhmm[.SS]] <file> ...

            
touch sets modification and access times of files to the current time of day. If the file does not exist, it is created with default permissions.
-a Changes the access time of the file. Does not change modification time unless -m is also specified.
-c Does not create the file if it does not exist.
-f Attempts to force the update, even if file permissions do not currently permit it.
-h If <file> is a symbolic link, changes access and/or modification time of the link. This option also implies -c.
-m Changes the modification time of the file. Does not change the access time unless -a is also specified.
-r <file> Replaces access and modification time with that of <file> , rather than using the current time.
-t Changes the access and modification time to the specified time.
The argument for -t should be in the form [[CC]YY]MMDDhhmm[.SS], where each pair of letters represents the following:
CC First two digits of the year (the century).
YY Second two digits of the year. If YY is specified but CC is not, a value for YY between 69 and 99 results in a CC value of 19. Otherwise, a value of 20 is used.
MM The month of the year, from 1 to 12.
DD The day of the month, from 1 to 31.
hh The hour of the day, from 0 to 23.
mm The minute of the hour, from 0 to 59.
SS The second of the minute, from 0 to 61.
If CC and YY letter pairs are not specified, the values default to the current year. If the SS letter pair is not specified, the value defaults to 0.

Share ThisShare This

Informit Network