In the previous chapter, we learned how to navigate the filesystem using pwd, ls, and cd. Now it is time to manipulate the content of the filesystem itself. This chapter covers commands for creating files and directories, copying, moving, and deleting them, viewing file contents, searching for files, using wildcards, and creating symbolic links. These skills form the core of daily terminal tasks and will be continuously used in subsequent chapters.
16.1 Creating Files and Directories
The first step in managing files is creating them. Linux provides simple commands to create empty files and new directories.
16.1.1 touch: Creating Empty Files
The touch command is used to create a new, empty file. Simply type touch followed by the file name you want to create:
touch notes.txtIf the file does not exist yet, touch will create it. If the file already exists, touch will update its modification timestamp without altering the file content. We can also create multiple files at once in a single command:
touch file1.txt file2.txt file3.txt16.1.2 mkdir: Creating Directories
The mkdir command (short for make directory) is used to create a new directory:
mkdir projectThis command creates a directory named project inside our active directory.
16.1.3 mkdir -p: Creating Nested Directories
By default, mkdir can only create one directory level at a time. If we want to create a nested directory structure, such as project/documents/2026, and the parent directories do not exist yet, use the -p (parents) option:
mkdir -p project/documents/2026The -p option creates all required parent directories simultaneously without raising an error even if some of the directories already exist. Without this option, mkdir will fail with an error message like mkdir: cannot create directory 'project/documents/2026': No such file or directory because the project and documents directories do not exist yet. Get into the habit of adding -p whenever creating a multi-level directory structure so you do not have to run mkdir repeatedly for each level.
16.2 Copying, Moving, and Deleting
Once files and directories are created, we need to know how to copy, move, and delete them.
16.2.1 cp: Copying Files or Directories
The cp command (short for copy) is used to copy files or directories. Its syntax pattern is cp source destination:
cp notes.txt backup.txtThis command copies notes.txt into a new file named backup.txt. To copy a directory along with all of its contents, use the -r (recursive) option:
cp -r project project-backupWithout the -r option, cp will refuse to copy directories. This option ensures that cp recursively includes all subdirectories and files contained inside.
Some additional useful options for cp:
-i(interactive): prompts for confirmation before overwriting an existing destination file. Make it a habit to add this option, especially when learning, for example:cp -i notes.txt backup.txt.-v(verbose): displays every file being copied, which is useful for monitoring copy operations involving many files.-a(archive): copies while preserving original permissions, ownership, and timestamps, and works recursively without needing to add-rexplicitly. This option is suitable when copying data where original attributes must be maintained, for example:cp -a project project-backup.
16.2.2 mv: Moving or Renaming
The mv command (short for move) serves two functions: moving files to a different location, or renaming files. Its syntax pattern matches cp, which is mv source destination:
mv notes.txt documents/This command moves notes.txt into the documents directory. If the destination is a file name, mv renames it instead:
mv notes.txt new-notes.txtUnlike cp, the mv command does not require a recursive option to move directories. Just like cp, mv also supports the -i option to prompt for confirmation before overwriting a destination file, and -v to display the move operation in detail. Because mv can overwrite destination files without any warning by default, getting comfortable with mv -i is a good habit when unsure about the end result.
16.2.3 rm: Deleting Files
The rm command (short for remove) is used to delete files or directories:
rm notes.txtTo delete a directory along with all of its contents, use the -r (recursive) option. The -f (force) option forces the deletion without asking for confirmation:
rm -r project-backup
rm -rf old-directoryIt must be emphasized that rm does not move files to a Recycle Bin. Files deleted with rm are permanently gone, and recovering them is nearly impossible. Therefore, use rm with caution, especially when combined with the -rf option.
As a safety measure, particularly while still learning, get into the habit of adding the -i option so that rm asks for confirmation before deleting each file:
rm -i notes.txtA common practice among Sysadmins is to verify the output of pwd or ls before running rm -rf on paths containing wildcards or variables, ensuring the command does not delete the wrong directory. A typo in a single path character, such as an unintentional space in rm -rf /var /log, can be fatal because the shell will interpret it as two separate arguments, namely /var and /log.
If we want behavior more similar to the Recycle Bin in Windows or Trash in macOS, GNOME provides a trash mechanism accessible from the terminal via the gio trash command (built into GLib/GNOME, available on both Ubuntu and Fedora). This command moves files to the Trash instead of permanently deleting them, allowing files to be restored via the Files application:
gio trash notes.txtAnother alternative is the third-party package trash-cli, which provides commands like trash-put with similar functionality. For truly permanent and intentional deletions, such as clearing cache files or temporary directories, rm remains the appropriate command.
16.2.4 rmdir: Deleting Empty Directories
The rmdir command (short for remove directory) can only delete empty directories:
rmdir empty-directoryIf the directory still contains files or subdirectories, rmdir will reject it with an error message. This makes rmdir a safer choice when we only intend to delete empty directories.
16.3 Viewing File Contents
After creating files, we naturally want to read their contents. Linux provides several commands to display text file contents.
16.3.1 cat: Displaying Full Content
The cat command (short for concatenate) displays the entire content of a file at once:
cat notes.txtThis command prints the full file content to the screen. cat can also be used to concatenate multiple files, such as cat file1.txt file2.txt, which displays the content of both sequentially. However, for very long files, cat is inconvenient because the output scrolls past immediately.
16.3.2 less and more: Reading Files Page by Page
For long files, use less or more. Both display file contents one screen at a time:
less long-notes.txtless is more modern and flexible than more. Inside less, we can scroll using the arrow keys or Page Up/Page Down, search for text by typing /word, and exit by pressing the q key. more only supports limited forward navigation, making less the recommended choice.
16.3.3 head and tail: Viewing Beginning and End of Files
head displays the first ten lines of a file, while tail displays the last ten lines:
head long-notes.txt
tail long-notes.txtWe can specify the number of lines using the -n option, such as head -n 5 file.txt for the first five lines. The tail command is exceptionally useful for monitoring continuously growing log files, especially with the -f (follow) option, which displays new lines in real-time. Sysadmins commonly rely on tail -f /var/log/syslog when troubleshooting active issues, as new log entries appear as soon as they are written by the system.
16.4 Searching for Files
As the number of files grows, the ability to find them quickly becomes increasingly important.
16.4.1 find: Criteria-Based Searching
The find command is the most powerful search tool in Linux. Its basic pattern is find location -name pattern:
find ~ -name "notes.txt"This command searches for a file named notes.txt inside our home directory and all of its subdirectories. We can use wildcard patterns, such as find ~ -name "*.pdf", to search for all PDF files. Note the quotes surrounding the pattern; the reason for this is discussed further in the Wildcard and Globbing section below.
Beyond searching by name, find can filter results by file type using the -type option, which is often used alongside -name:
find ~ -type f -name "*.pdf": searches only for regular files (f) with a.pdfextension, ignoring directories that happen to share a similar name.find ~ -type d -name "project*": searches only for directories (d) whose names start withproject.
find can also search by size (-size) and modification time (-mtime), but the -name and -type criteria above cover most day-to-day beginner needs.
16.4.2 locate: Database-Based Searching
locate works differently: it searches through a pre-indexed database rather than scanning the filesystem directly. As a result, locate is much faster than find:
locate notes.txtBecause it relies on a database, locate results might not reflect newly created or recently deleted files. We can manually update its database using the command sudo updatedb, although updates are typically scheduled automatically every day.
The locate command is not always installed by default and may need to be installed first. The implementation used by current Ubuntu 26.04 LTS and Fedora Workstation 44 releases is plocate, a modern version of locate that is faster and more space-efficient than the older mlocate, while remaining fully compatible with the same locate command interface:
sudo apt install plocate # on Ubuntu
sudo dnf install plocate # on FedoraOnce installed, we still invoke it using the standard locate command; the plocate package name simply refers to the underlying implementation.
16.4.3 which and whereis: Locating Program Paths
which displays the location of the executable program that will run when we type its command:
which python3This command shows the full path of the python3 executable, for instance, /usr/bin/python3. Meanwhile, whereis provides broader information, including the locations of binary files, manual pages, and source code:
whereis python3Both commands are useful for verifying that a given program is installed and discovering its location.
16.5 Wildcards and Globbing
Wildcards are special characters used to match multiple file names simultaneously. This matching mechanism is called globbing and is extremely useful when working with multiple files. The three primary wildcards are:
*: matches zero or more of any characters. For example,*.txtmatches all files ending in.txt.?: matches exactly one single character. For example,file?.txtmatchesfile1.txt, but notfile12.txt.[abc]: matches any single character contained within the brackets. For example,file[123].txtmatchesfile1.txt,file2.txt, orfile3.txt.
Wildcards are typically combined with other commands. For example:
ls *.txt
rm file?.log
cp *.jpg images/The first command lists all .txt files, the second removes log files matching a single variable character, and the third copies all JPG files into the images directory. Wildcards make operations involving large sets of files significantly more efficient.
It is important to note that wildcards are actually processed by the shell, not by the executed command itself. In the ls *.txt example, the shell expands *.txt into a list of matching file names in the active directory before passing them to ls. This is why the pattern in the earlier find ~ -name "*.pdf" command needed to be wrapped in quotes: without quotes, the shell would expand *.pdf prematurely based on the current directory contents, rather than letting find evaluate the pattern recursively across subdirectories. Keeping the habit of quoting search patterns when using find is essential to avoid unexpected search results.
16.5.1 Handling File Names with Spaces or Special Characters
As mentioned in Chapter 11, Linux permits spaces within file names, such as Meeting Notes.txt. However, the shell interprets spaces as argument delimiters, causing commands like rm Meeting Notes.txt to be treated as two separate arguments, Meeting and Notes.txt, which can lead to unintended deletions if matching files exist.
To safely manage these file names, we can enclose them in double quotes or use an escape character (\) before each space:
rm "Meeting Notes.txt"
rm Meeting\ Notes.txtThe most practical and low-risk approach is to type part of the file name and press Tab to leverage tab completion (see Chapter 14), as the shell automatically inserts the required escape characters for us.
16.6 Symbolic Links
A symbolic link (or symlink) is a special file pointing to another file or directory, similar to a shortcut in Windows. The command to create one is ln with the -s (symbolic) option:
ln -s /home/username/project project-shortcutThis command creates a symlink named project-shortcut that points to the /home/username/project directory. Accessing project-shortcut seamlessly routes us to the original directory.
Symlinks are useful for creating quick access shortcuts to long file paths, or when an application expects a file at a specific path while the actual file resides elsewhere. For instance, developers frequently use symlinks to point projects to shared dependency directories or make multiple configuration versions accessible via a single consistent path without duplicating files. Note that if the original target file is deleted, the symlink becomes "broken" and non-functional, though the symlink file itself remains.
Additionally, running ln without the -s option creates a different type of link known as a hard link. Unlike symlinks that act as pointers to another path, a hard link points directly to the underlying inode number of the original file, as explained in Chapter 11's inode concepts. Consequently, a hard link continues to function normally even if the original file name is deleted, because actual data is only purged when no remaining references point to its inode. However, hard links have limitations: they cannot point to directories and cannot cross different partitions or filesystems, making symlinks much more widely used in day-to-day operations.
In this chapter, we covered core commands for managing files and directories: creating files with touch, creating directories with mkdir and mkdir -p, copying with cp (including -i, -v, and -a options), moving and renaming with mv, as well as deleting with rm, rmdir, and safer alternatives like gio trash. We also learned how to inspect file contents using cat, less, more, head, and tail, locate files using find (including -type filtering), locate/plocate, which, and whereis, leverage wildcards while handling spaced filenames, and construct symbolic links while understanding their differences from hard links.
In the next chapter, we will learn how to obtain help when forgetting or trying to understand a command, using man, --help, info, and tldr.

