Lesson 3: Moving, Copying, and Deleting Files and Directories
In the previous two installments in this series, we looked at the basics of using the Terminal to access the Unix command line at the heart of Mac OS X, and then at how to use the Terminal to move around your Mac's file system. You might want to skim those articles for a quick refresher on some of the basics.
One of the strongest features of the Mac OS X Finder is its capability to make file management actions so easy that they seem effortless. When you drag a file's icon from one window to another, for example, the Finder puts a graphical face on a basic action, that of issuing a command to move a file from one location to another.
It's certainly quicker and easier to move icons in Finder windows than to type commands, but the command line offers advantages over using the Finder for moving, copying, or deleting files and folders (or directories). Here are just a few:
You can copy or move files from one directory to a distant directory, without having to navigate through intermediate windows.
You can easily copy or move multiple files using wildcards (a wildcard is a single character that represents one or more other characters). You can even select which files to copy according to certain attributes, such as parts of file names or extensions.
You can copy or move files that are hidden by the Finder.
You can move and rename a file or directory with just one command.
You can delete files or directories quickly, and use wildcards to match certain file name strings (such as .jpg, .rtf, and so on). These deletions are irreversible, so be careful!
You can delete files that the Finder refuses to delete; occasionally, a recalcitrant file you have placed in the Trash just won't go away. Using the command line, you can eliminate it for good.
As you become more familiar with working with the command line, you will discover more advantages to using it for file manipulation.
A Caveat on Moving and Copying Files -- The Mac OS has historically used a unique way of saving files: many files are in two parts, called the data fork and the resource fork. Back in the days of Mac OS 9 and earlier, the data fork contained data (the contents of a file, or code for applications) and the resource fork contained settings, icons, and other information. Most files used this multi-fork system, and, if you ever copied Mac files to a PC-formatted floppy disk and then looked at it on a Windows computer, you could have seen additional folders copied together with your files. These folders held resources forks; since Windows doesn't understand multi-forked files, putting the resource forks in a separate folder was one way of keeping Windows from deleting them altogether. Unfortunately, and almost shockingly, the standard Unix commands available in Mac OS X don't understand resource forks either.
When copying or moving files containing a resource fork, this can be a serious problem: some files still contain information in a resource fork, especially applications and those files created by Classic applications, as well as some Mac OS X-native applications. The cp and mv commands strip any resource forks they come across, potentially rendering the files useless. Apple addressed this problem by creating some additional commands, called CpMac and MvMac (the capitalization is important here), to resolve these issues, but for some reason, these commands are installed only with the Developer Tools, so most people probably don't have them installed. These command line tools enable you to copy and move files while retaining their resource forks, thus ensuring that everything you copy or move with them remains usable.
Another command, called ditto, has a -rsrcfork option, which, like CpMac and MvMac, allows you to retain resource forks when copying files.
Copying Files with cp -- The cp (copy) command does exactly what its name suggests: it copies files from one location to another. (This is the equivalent of pressing Option while dragging files in the Finder from one window to another on the same volume.) In its simplest use, cp copies a file (specified by its file name, with either a relative or absolute path) to a directory (also specified by its name, with either a relative or absolute path). The basic form is as follows:
% cp source destination
With this in mind, let's look at a few examples of copying files.
% cp ~/Documents/MyFile.rtf ~/Public
In the above example, I copied the file "MyFile.rtf" from the Documents directory in my Home directory to the Public directory, a location where any user can access files. As you can see, the first part, cp, is the command, the second, ~/Documents/MyFile.rtf, is the source, and the third part, ~/Public, is the destination. Both the source and destination in this example use absolute file paths; I could be anywhere in the file system when running this command.
However, if I were already in the Documents directory, I wouldn't need to use an absolute file path for the source. Since it's perfectly legal to mix absolute and relative file paths in a command, I could merely type the following:
% cp MyFile.rtf ~/Public
When copying files in this simple form, the source is a file name and the destination is a directory. (Though the destination can also be a file name; see below for more ways to use cp.) But the source can also be multiple file names. When executing this command, the shell (which is the Unix program that accepts your typed commands, interprets them, and displays the results) checks the contents of the directory you refer to, making sure that the file or files exist. If there are several files listed in what you've typed, and they all exist, then the shell goes ahead and copies them all to the destination. You can run a command like this to copy the three files after the cp command to the Public directory:
% cp MyFile1.rtf MyFile2.rtf MyFile3.rtf ~/Public
Using Wildcards to Copy Files -- For an even shorter version of the previous command, you can use a wildcard and save some typing:
% cp MyFile* ~/Public
The * wildcard tells the shell to look for all files whose names begin with MyFile, and copy them to ~/Public. Of course, if you have 10 files like that, all 10 will be copied. If you want only the first three copied, you must enter each name individually, or you could use the following command:
% cp MyFile[1-3].rtf ~/Public
If you want to copy all .rtf files from the source directory, you can use the following:
% cp *.rtf ~/Public
This command copies all files ending with .rtf to the Public folder. You can use the asterisk wildcard at any location in a file name.
Warning: Copying Files Replaces Existing Files -- By default, the cp command silently replaces any like-named files in the destination, unlike the Finder, which displays an alert asking if you really want to replace them. The same goes for the mv command (see below). This is one of the dangers of using the command line - new actions call for new habits, and the safest way to work with these two commands is to use the -i (interactive) option, which tells the shell to ask you if any files with the same name are present. When using this option, type
y for yes (to replace files) and
n for no. Here's an example:
% cp -i MyFile1.rtf New_Directory/ overwrite New_Directory/MyFile1.rtf? y %
If I had typed
n at the overwrite question, the command would have stopped without doing anything.
Copying a File and Changing Its Name -- In the above examples, the sources used were files and destinations directories. But the destination can also be a file name. This is useful if you want to copy a file and change its name at the same time. For example, to copy MyFile.rtf to your Public folder, renaming it MyFile1.rtf, run the following command:
% cp MyFile.rtf ~/Public/MyFile1.rtf
You can do the same thing to make a copy of a file, with a different name, in the same folder. Just run the command like this:
% cp MyFile.rtf MyFile1.rtf
Copying Directories with cp -- You can use cp to copy directories as well as files, but it works a bit differently. For cp to work with directories, it needs the -R (recursive) option. The -R option tells cp to copy not only the directory specified, but also all sub-directories it contains as well as any other contents. To copy a directory, you need to run a command using this basic form:
% cp -R source destination
All the other options and ways of copying, shown above for files, work the same with directories. Note, however, that while you can change the name of a directory during a copy, you cannot change the name of its sub-directories or other contents.
Moving Files and Directories with mv -- The mv (move) command moves files or directories from one location to another. It works just like when you drag files from one Finder window to another on the same volume. Note that if you run the mv command across volumes, the files or directories are removed from their original location, whereas the Finder normally copies them across volumes unless you hold down Command while dragging them. The mv command thus acts like a cut and paste operation, cutting the file or directory from its original location, and pasting it in its new location. The mv command works almost exactly like the cp command, the main exception being that you never have to use the -R option to move directories. To use mv, try the examples described above, substituting mv for cp.
% mv MyFile.rtf ~/Public/MyFile.rtf
In the above example, the file called MyFile.rtf is moved to my Public folder. The operating system first writes the file, then, after checking to make sure the copied file was written correctly, it deletes the original.
By default, the mv command (just like cp) replaces any like-named files in the destination. This behavior is unlike the Finder, which displays an alert, asking if you really want to replace them. You can run the mv command with the -i (interactive) option, as with many commands, to protect against this possibility.
Renaming Files and Directories with mv -- Since you can change the name of the destination when moving files or directories with mv, you can also use it to rename items, such as in this example:
% mv MyFile.rtf NewlyNamed.rtf
Unfortunately, renaming a bunch of files at once with wildcards (such as prefixing each of many files with a specific string) isn't trivial; the best way to do that is with the Add and Trim AppleScript scripts that Apple includes with Mac OS X; you can find them in /Library/Scripts/Finder Scripts.
Creating Directories with mkdir -- We have seen above how to move and copy files from one directory to another, but you may also need to create directories to put these files in. The mkdir (make directory) command is easy to use. Here's an example:
% mkdir Test
This command creates a new directory, called Test, in the current directory. Since the command does not begin with a /, the shell knows that you are specifying a relative path. If you want to create the same directory in, say, your Documents directory, you could run the above command after using cd (change directory) to move to that directory, or, from anywhere, run the following:
% mkdir ~/Documents/Test
The mkdir command can also make several directories at a time. If you want to create three directories, called Test1, Test2, and Test3, in the current working directory, you can run the following:
% mkdir Test1 Test2 Test3
If you want to create directories in hierarchy, mkdir can help as well. The only condition is that you set up your command in hierarchical order, creating the parent directory before the sub-directory, and before the sub-sub-directory, and so on. To create a series of directories and sub-directories like this:
you need to run the command as follows:
% mkdir -p Test1/Test2/Test3
The -p (path) option tells the command to create each intermediate directory as required. The command first creates the Test1 directory, then the Test2 sub-directory, and finally, further down in the hierarchy, Test3.
Removing Directories with rmdir -- The rmdir (remove directory) command is self-explanatory: it lets you remove directories, deleting them forever. Like the rm command that works on files, this command is extremely powerful: once you remove a directory, there is no getting it back.
However, rmdir works only with empty directories, whereas rm works with both directories and files, thus enabling you to delete a directory and the files in it. You may find it easier to use rm for both files and directories - it's easier to use one command instead of two.
To delete an empty directory, run the following:
% rmdir Directory1
You can remove several empty directories in one command. Just separate their names with single spaces, specifying either just their names (for relative paths, within the current working directory), or their paths (for absolute paths). Here's an example that removes three directories at once - Directory1, OldDocuments, and Video - and uses a different way of specifying each one:
% rmdir Directory1 ~/Documents/OldDocuments ../Video
You can also use rmdir to remove a hierarchy of directories, as long as all the directories are empty. Use the -p (path) option as follows:
% rmdir -p Directory1/Directory2/Directory3
One disadvantage to using the rmdir command is that, unlike the rm command, it has no -i (interactive) option, which asks you to confirm the deletion, and no -v (verbose) option; these deficiencies limit its value.
Removing Files with rm -- The rm (remove) command is one of the most powerful and dangerous commands you can use in the Terminal. Be forewarned: when you remove a file with rm, it is deleted forever. Although some file recovery programs may be able to find files deleted in this manner, it is safest to assume that files eliminated with rm are gone for good. Be even more careful with rm if you use it with the * wildcard, since it could wipe out all the files in a directory with no warning.
Although many Unix commands are safe to run, even if you have little experience, rm is like a loaded gun. For this reason, you should use it with the utmost care. However, there is a simple way to apply a safeguard to rm (and others); see below for a safety measure that takes the worry away.
Running the rm command is relatively simple. Look at the contents of this directory with ls:
% ls File1 File2 File3
To remove one of these files, run the following:
% rm File1
Check to make sure it worked with ls again:
% ls File2 File3
You can see that the file you removed is indeed gone; it no longer shows up in the list.
Safer Ways Remove Files -- The first way of removing files, as shown above, is really for those people who are confident with the command line. It's working without a net, though, and there is a simple safeguard you can use to protect yourself. The rm command has an option, -i (for interactive), which tells the shell to ask you to confirm that you really want to delete each file. To use this option, run the command as follows:
% rm -i File2
The shell asks you to confirm.
y for yes or
n for no.
remove File2? y
If you type
y, the file will be deleted. If you type
n, the file will not be touched. In both cases, the Terminal displays a new prompt; it gives no other information, and you need to use ls again to see what's in the directory.
Want an even safer way to remove files? Mimic the way the Finder does it and move them to the Trash. Then they won't be deleted until you empty the Trash manually. Try this mv command:
% mv MyFilertf ~/.Trash
Getting More Feedback with rm -- The rm command has another option, -v (verbose), which shows the names of files as it removes them. If you use this option, the shell shows the following:
% rm -v File3 File3 %
I have added the prompt after the file removal to illustrate how this displays. All this option does is show the name of the file, but it can serve to confirm exactly which file has been removed. Of course, if you made a typo and removed the wrong file, it's too late!
Removing Directories with rm -- Although you can use rmdir for removing empty directories, the rm command also lets you do this through the -d option. To remove a directory, use the following command, along with the -i and -v options for additional security:
% rm -div Directory1
The rm command can also remove directories recursively, using the -r (recursive) option, deleting a directory and all its subdirectories, as well as any files they contain. This is like dragging a folder, containing sub-folders and files, to the Trash in the Finder, except you can't drag it back out of the Trash if you want to keep it. If rm is a loaded gun, rm -r is a loaded bazooka. I cannot stress strongly enough how dangerous this command is, since you could blow away large numbers of files with a single mistake!
Let's look at how this works, and how you can use the -i option for minimal protection. First, create a few nested directories:
% mkdir -p Directory1/Directory2/Directory3
Then, to remove all three of these directories, run the following:
% rm -ir Directory1 remove Directory1? y remove Directory1/Directory2? y remove Directory1/Directory2/Directory3? y
Obviously, if you don't use the -i option, the command just removes all the directories without any feedback. But what if you decide you don't want to remove one of the directories? You can type
n at any point to keep it and each directory above it. Watch what happens then:
% rm -ir Directory1 remove Directory1? y remove Directory1/Directory2? y remove Directory1/Directory2/Directory3? n rm: Directory1/Directory2: Directory not empty rm: Directory1: Directory not empty
If, at any point in the hierarchy, you don't want to delete a file or directory, the system cannot let you keep an item without its parent directory. In the above example, the decision to not remove Directory3 means that Directory2 (its parent directory) could not be deleted; Directory1 (the parent of Directory2) also could not be deleted, so none of these three directories will be removed.
Summing Up -- This installment has shown you the essential commands for copying, moving, and deleting files and directories, as well as creating directories. These commands - cp, mv, rm, mkdir and rmdir - offer the same basic functions as normal Finder actions, but, as some of the examples show, offer more power and flexibility in certain situations. While the Finder remains easier to use for most operations, these commands give you a powerful alternative, with some capabilities the Finder cannot offer.
[Kirk McElhearn is a freelance writer and translator living in a village in the French Alps. This article is an excerpt from his forthcoming book, Unix for Mac OS X: Learning the Command Line, to be published by Addison-Wesley in 2003.]
PayBITS: Did this article help you dip your toes into Terminal?
Consider supporting Kirk with a few bucks via PayPal!
Read more about PayBITS: <http://www.tidbits.com/paybits/>