4 Class 4. Working with files and directories
Moving (and renaming) files and directories
Today we’ll practice how to rename and move files or directories. For this example, let’s imagine we begin in a directory called thesis that we’ll access by using the command:
cd ~/Desktop/data-shell/thesis
In our thesis
directory we have a file draft.txt
which isn’t a particularly informative name, so let’s change the file’s name to quotes.txt
using mv
, which is short for ‘move’:
$ mv draft.txt quotes.txt
The first argument tells mv
what we’re ‘moving’, while the second is where it’s to go. In this case, we’re moving draft.txt
to quotes.txt
, which has the same effect as renaming the file. Sure enough, ls
shows us that thesis
now contains one file called quotes.txt
:
$ ls thesis
quotes.txt
One has to be careful when specifying the target file name, since mv
will silently overwrite any existing file with the same name, which could lead to data loss. An additional option, mv -i
(or mv --interactive
), can be used to make mv
ask you for confirmation before overwriting. Note that mv
also works on directories.
You do not have to be in the same directory as a file to change its name. For example, in the previous example, you could achieve the same goal with the following steps:
Move to the parent directory of thesis:
$ cd ~/Desktop/data-shell/
Change the name of a file within the thesis directory:
$ mv thesis/draft.txt thesis/quotes.txt
Now let’s move quotes.txt
into our current working directory (data-shell
). We use mv
once again, but this time we’ll use just the name of a directory as the second argument to tell mv
that we want to keep the filename, but put the file somewhere new. (This is why the command is called ‘move’.) In this case, the directory name we use is the special directory name .
that we mentioned earlier.
$ mv thesis/quotes.txt .
The effect is to move the file from the directory it was in to the current working directory. ls
now shows us that thesis
is empty:
$ ls thesis
Further, ls
with a filename or directory name as an argument only lists that file or directory. We can use this to see that quotes.txt
is still in our current directory:
$ ls quotes.txt
quotes.txt
Copying files and directories
The cp
command works very much like mv
, except it copies a file instead of moving it. We can check that it did the right thing using ls
with two paths as arguments — like most Unix commands, ls
can be given multiple paths at once.
The basic usage of this command is $cp target_file name_of_copy
$ cp quotes.txt thesis/quotations.txt
$ ls quotes.txt thesis/quotations.txt
quotes.txt thesis/quotations.txt
We can also copy a directory and all its contents by using the recursive option -r
, e.g. to back up a directory:
$ cp -r thesis thesis_backup
We can check the result by listing the contents of both the thesis
and thesis_backup
directory:
$ ls thesis thesis_backup
thesis:
quotations.txt
thesis_backup:
quotations.txt
Creating Files a Different Way
We have seen how to create text files using the nano
editor. Now, try the following command:
$ touch my_file.txt
The touch
command generates a new file called my_file.txt
in your current directory. You can observe this newly generated file by typing ls
at the command line prompt. my_file.txt
can also be viewed in your GUI file explorer. When you inspect the file with ls -l
, note that the size of my_file.txt
is 0 bytes. In other words, it contains no data. If you open my_file.txt
using your text editor it is blank.
When might you want to create a file this way? Some programs do not generate output files themselves, but instead require that empty files have already been generated. When the program is run, it searches for an existing file to populate with its output. The touch command allows you to efficiently generate a blank text file to be used by such programs.
Using wildcards for accessing multiple files at once
*
is a wildcard, which matches zero or more characters. Let’s consider the data-shell/molecules
directory: *.pdb
matches ethane.pdb
, propane.pdb
, and every file that ends with ‘.pdb’. On the other hand, p*.pdb
only matches pentane.pdb
and propane.pdb
, because the ‘p’ at the front only matches filenames that begin with the letter ‘p’.
?
is also a wildcard, but it matches exactly one character. So ?ethane.pdb
would match methane.pdb
whereas *ethane.pdb
matches both ethane.pdb
, and methane.pdb
.
Wildcards can be used in combination with each other e.g. ???ane.pdb
matches three characters followed by ane.pdb
, giving cubane.pdb ethane.pdb octane.pdb
.
When the shell sees a wildcard, it expands the wildcard to create a list of matching filenames before running the command that was asked for. As an exception, if a wildcard expression does not match any file, Bash will pass the expression as an argument to the command as it is. For example typing ls *.pdf
in the molecules
directory (which contains only files with names ending with .pdb
) results in an error message that there is no file called *.pdf
. However, generally commands like wc
and ls
see the lists of file names matching these expressions, but not the wildcards themselves. It is the shell, not the other programs, that deals with expanding wildcards, and this is another example of orthogonal design.