Working with files and directories
Last updated on 2026-10-21 | Edit this page
Estimated time: 25 minutes
Overview
Questions
- How can I create, copy, move, and delete files and directories?
- How can I read files?
Objectives
- apply file naming conventions under guidance when creating a project directory
- apply shell commands to create, view, rename, copy and delete files and directories
- apply tab completion, the command history and wildcards to save typing
Working with files and folders
As well as navigating directories, we can interact with files on the command line: we can create them, read them, rename them and delete them. In fact, there’s really no limit to what we can do in the shell, but even experienced shell users still switch to graphical user interfaces (GUIs) for many tasks, such as editing formatted text documents, browsing the web or editing images. But if we wanted to make the same change to hundreds of files, say, rename all the images of a scanned book, then we could automate that work by using shell commands.
Creating a project directory
Let’s create a directory for the project we will work on for the rest of this workshop. First, we move to the Desktop, so that we can easily find the directory in the graphical file manager, too:
OUTPUT
/Users/riley/Desktop
Where is my Desktop?
On some Windows computers, the Desktop is inside a OneDrive folder,
for example OneDrive/Desktop. If cd Desktop
doesn’t work, ask your instructor for help.
Here, we create a new directory with the mkdir command
(meaning ‘make directories’). We call it my-git-repo-
followed by our first name in lower case letters, for example
my-git-repo-riley. Please use your own name instead of
<name> in the commands of this lesson:
OUTPUT
my-git-repo-riley
Why add your name?
Later in the workshop, this directory will become a repository on Codeberg, next to the repositories of all other participants, and you will work with the repository of a partner. If everybody’s repository had the same name, it would be easy to mix them up. With your name in it, it’s always clear whose repository you are looking at.
Now let’s move into the new directory. But wait! There’s a trick to
make things a bit quicker. Instead of typing the whole name, type
cd my and then press the Tab key. We notice that
the shell completes the line to cd my-git-repo-riley/.
Press Enter to run the command.
OUTPUT
/Users/riley/Desktop/my-git-repo-riley
Tab for Auto-complete
Pressing tab at any time within the shell will prompt it to attempt to auto-complete the line based on the files or sub-directories in the current directory. Where two or more files have the same characters, the auto-complete will only fill up to the first point of difference, after which we can add more characters, and try using tab again. We would encourage using this method throughout today to see how it behaves (as it saves loads of time and effort!).
Creating and reading files
Our directory is still empty. Every project should have a
README.md file that explains what the project is about, so
let’s create one. To create a new, empty file, we can use the
touch command:
OUTPUT
README.md
The .md extension signifies that we have chosen to use
the Markdown format, a lightweight markup language with plain text
formatting syntax. We will see more of Markdown later.
To write something into a file, we would usually use a text editor,
which we will meet in the Git episodes. For a quick start, we can also
use the echo command, which prints a text, together with
>, which sends the output of a command into a file
instead of to the screen:
The hash character # at the beginning of the line makes
it a heading in Markdown.
> overwrites files
If the file after > already exists, its content is
replaced without warning. Use >> instead to add a
line at the end of a file.
To look at the content of the file, we use the cat
command:
OUTPUT
# My Git repository
Re-using commands
On a blank command prompt, press the up arrow key and notice that the previous command you typed appears before your cursor. We can continue pressing the up arrow to cycle through your previous commands. The down arrow cycles back toward your most recent command. This is another important labour-saving function and something we’ll use a lot.
Adding a line
Use the up arrow key to get back the echo command, and
change it so that it adds the line “This is where I practise
Git.” to README.md. Then check the content of the file.
cat prints the whole file to the screen. For long files,
this is not very practical, so there are a few more commands to view
files. Try them with README.md:
-
head README.mdshows the first ten lines of a file (head -n 1 README.mdonly the first line), -
tail README.mdshows the last ten lines (tail -n 1 README.mdonly the last line), -
less README.mdshows the file one screen at a time: use the spacebar to go to the next screen and q to quit.
Remember how to quit less with q: Git uses
less to show long output, for example the history of a
project with git log.
Moving, copying and deleting files
Instead of moving a file, you might want to copy a
file (make a duplicate), for instance to make a backup before modifying
a file. The cp command takes two arguments: the old name
and the new name.
OUTPUT
README-backup.md README.md
We may also want to change a file name to something more descriptive.
We can move it to a new name by using the
mv or move command, giving it the old name as the first
argument and the new name as the second argument:
OUTPUT
README.md old-readme.md
This is equivalent to the ‘rename file’ function.
Moving a file into a directory
If the last argument you give to the mv command is a
directory, not a file, the file given in the first argument will be
moved to that directory. Create a directory called backup
and use the mv command to move the file
old-readme.md into it. Check the result with
ls and ls backup.
If we had lots of files, it would be tedious to type all the
filenames. Luckily the shell supports wildcards! The ?
matches exactly one character and * matches zero or more
characters. For example, ls backup/*.md lists all files in
the backup directory whose names end in
.md.
More on wildcards
Wildcards are a feature of the shell and will therefore work with
any command. The shell will expand wildcards to a list of files
and/or directories before the command is executed, and the command will
never see the wildcards. As an exception, if a wildcard expression does
not match any file, Bash will pass the expression as a parameter to the
command as it is. For example typing ls *.pdf results in an
error message that there is no file called *.pdf.
Finally, onto deleting. The command to delete a file is
rm, or remove. Adding the -r flag, we can
delete directories with all their content.
Unlike deleting from within our graphical user interface,
there is no warning, no recycling bin from which you
can get the files back and no other undo options! For that
reason, please be very careful with rm and extremely
careful with rm -r.
Let’s clean up and delete the backup, so that only our
README.md is left before we start with Git:
OUTPUT
README.md
Version control as a safety net
Git cannot protect you from rm either, but it can help a
lot: if a file is part of a Git repository and its changes are
committed, you can get the last committed version back even after
deleting it. This is one of many reasons to use version control, as we
will see next.
-
mkdircreates a directory andtouchcreates an empty file -
echo "text" > filewrites text into a file,>>adds it at the end -
cat,head,tailandlessshow the content of files -
mvmoves or renames,cpcopies andrmdeletes files – there is no undo forrm - Tab completion, the up arrow key and wildcards (
*,?) save a lot of typing