Oftentimes one needs to copy or move several files at once. This can be done by providing a list of individual filenames, or specifying a naming pattern using wildcards.
For this exercise, you can test the commands in the shell-lesson-data/data
directory.
In the example below, what does cp
do when given several filenames and a directory name?
$ mkdir backup
$ cp amino-acids.txt animals.txt backup/
In the example below, what does cp
do when given three or more file names?
$ ls -F
amino-acids.txt animals.txt backup/ elements/ morse.txt pdb/
planets.txt salmon.txt sunspot.txt
$ cp amino-acids.txt animals.txt morse.txt
*
is a wildcard, which matches zero or more characters.
Let’s consider the shell-lesson-data/alkanes
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. {: .callout}
When run in the alkanes
directory, which ls
command(s) will
produce this output?
ethane.pdb methane.pdb
ls *t*ane.pdb
ls *t?ne.*
ls *t??ne.pdb
ls ethane.*
You’re starting a new experiment and would like to duplicate the directory structure from your previous experiment so you can add new data.
Assume that the previous experiment is in a folder called ‘2016-05-18’,
which contains a data
folder that in turn contains folders named raw
and
processed
that contain data files. The goal is to copy the folder structure
of the 2016-05-18-data
folder into a folder called 2016-05-20
so that your final directory structure looks like this:
2016-05-20/
└── data
├── processed
└── raw
Which of the following set of commands would achieve this objective? What would the other commands do?
$ mkdir 2016-05-20
$ mkdir 2016-05-20/data
$ mkdir 2016-05-20/data/processed
$ mkdir 2016-05-20/data/raw
$ mkdir 2016-05-20
$ cd 2016-05-20
$ mkdir data
$ cd data
$ mkdir raw processed
$ mkdir 2016-05-20/data/raw
$ mkdir 2016-05-20/data/processed
$ mkdir -p 2016-05-20/data/raw
$ mkdir -p 2016-05-20/data/processed
$ mkdir 2016-05-20
$ cd 2016-05-20
$ mkdir data
$ mkdir raw processed
Bash also supports brace expansion whereby multiple paths can be created with a single expression. For example to reproduce the folder structure only a single command is needed:
$ mkdir -p 2016-05-20/data/{raw, processed}
As bash expands it to:
$ mkdir -p 2016-05-20/data/raw 2016-05-20/data/processed
This can be useful when creating nested file structures or when creating multiple directories quickly.