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:

BASH

$ cd
$ cd Desktop
$ pwd

OUTPUT

/Users/riley/Desktop
Callout

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:

BASH

$ mkdir my-git-repo-<name>
$ ls

OUTPUT

my-git-repo-riley
Callout

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.

BASH

$ cd my-git-repo-<name>
$ pwd

OUTPUT

/Users/riley/Desktop/my-git-repo-riley
Callout

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:

BASH

$ touch README.md
$ ls

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:

BASH

$ echo "# My Git repository" > README.md

The hash character # at the beginning of the line makes it a heading in Markdown.

Caution

> 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:

BASH

$ cat README.md

OUTPUT

# My Git repository
Callout

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.

Challenge

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.

BASH

$ echo "This is where I practise Git." >> README.md
$ cat README.md

OUTPUT

# My Git repository
This is where I practise Git.

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.md shows the first ten lines of a file (head -n 1 README.md only the first line),
  • tail README.md shows the last ten lines (tail -n 1 README.md only the last line),
  • less README.md shows 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.

BASH

$ cp README.md README-backup.md
$ ls

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:

BASH

$ mv README-backup.md old-readme.md
$ ls

OUTPUT

README.md  old-readme.md

This is equivalent to the ‘rename file’ function.

Challenge

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.

BASH

$ mkdir backup
$ mv old-readme.md backup
$ ls backup

OUTPUT

old-readme.md

This would also work:

BASH

$ mv old-readme.md backup/old-readme.md

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.

Callout

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:

BASH

$ rm -r backup
$ ls

OUTPUT

README.md
Callout

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.

Key Points
  • mkdir creates a directory and touch creates an empty file
  • echo "text" > file writes text into a file, >> adds it at the end
  • cat, head, tail and less show the content of files
  • mv moves or renames, cp copies and rm deletes files – there is no undo for rm
  • Tab completion, the up arrow key and wildcards (*, ?) save a lot of typing