Advanced Linux System Fundamentals
Advanced File Operations
Smarter Ways to Select Files
You're comfortable with ls for listing files and cd for changing directories. But when you need to handle hundreds of files at once, these basic tools fall short. Let's explore more powerful ways to select and act on files based on patterns.
First up is globbing, a feature of the shell that expands a wildcard pattern into a list of matching filenames. You've likely used the asterisk * to match any number of characters, like ls *.c to list all C source files. But globbing is more nuanced than that.
You can match specific characters using square brackets []. For example, ls report_[abc].txt would match report_a.txt, report_b.txt, and report_c.txt, but not report_d.txt. You can also specify a range, like [0-9] to match any digit.
Brace expansion {} is another powerful tool. It generates arbitrary strings. It's not technically globbing, but it serves a similar purpose. For instance, you could create several directories at once:
# Create directories for different project stages
mkdir -p project/{source,build,docs,assets}
This single command creates four distinct directories inside project. It's a concise way to set up structured folders or generate a series of related filenames.
Find and Act
Globbing is great for simple patterns in a single directory, but it can't search recursively or filter by metadata like modification time or file type. For that, we need the find command. It's a surgical tool for locating files anywhere in the filesystem based on complex criteria.
The basic structure is:
find [path] [expression]
The path tells find where to start looking, and the expression specifies what to look for. For example, to find all C files in your home directory, you'd use:
# Search from the home directory (~)
find ~ -type f -name "*.c"
Here, -type f limits the search to regular files (not directories), and -name "*.c" specifies the filename pattern. Notice the quotes around "*.c". This prevents the shell from globbing the asterisk; we want the find command itself to handle the pattern matching.
Finding files is only half the battle. The real power comes from executing commands on the results. The -exec flag lets you run any command on each file that find discovers.
# Find all temporary .tmp files older than 7 days and delete them
find /tmp -type f -name "*.tmp" -mtime +7 -exec rm {} \;
Let's break that down:
-mtime +7: Finds files modified more than 7 days ago.-exec rm {} \;: For each file found, execute thermcommand. The{}is a placeholder thatfindreplaces with the current filename. The\;marks the end of the command.
While -exec is powerful, it can be inefficient because it launches a new process for every single file. A more performant alternative for bulk operations is to pipe the results to the xargs command.
# A more efficient way to delete the same files
find /tmp -type f -name "*.tmp" -mtime +7 | xargs rm
xargs reads items from standard input (the list of files from find) and executes the given command (rm) with as many items as possible at once. This avoids the overhead of starting a new rm process for each file.
How Files Are Indexed
To truly master file manipulation, you need to understand how the Linux filesystem works under the hood. When you create a file, the system doesn't just store the data and a name. It creates a data structure called an inode (index node).
The inode stores all the file's metadata: its permissions, owner, size, timestamps, and, most importantly, the location of the file's data on the disk. The filename itself is just a convenient, human-readable label stored in a directory that points to this inode number. This separation of name from metadata is key to understanding links.
A hard link is a second filename that points to the exact same inode. It's not a copy; it's another entry point to the same data. Every file starts with one hard link (its original name). If you delete one of the hard links, the file data remains on the disk as long as at least one other link points to its inode. The data is only truly deleted when the link count drops to zero.
A symbolic link (or symlink) is different. It's a special type of file that doesn't point to an inode but to another file path. Think of it as a shortcut. If the original file is deleted or moved, the symlink becomes a "broken" link, whereas a hard link would remain valid because it points directly to the inode.
# Create a hard link
ln original.txt hardlink.txt
# Create a symbolic link
ln -s original.txt symlink.txt
You can inspect a file's metadata, including its inode number and link count, using the stat command. This is invaluable for debugging and understanding the state of your files.
stat original.txt
The output will show you the inode number, number of links, access times, and more. If you run stat on a hard link, you'll see it has the same inode number as the original. If you run it on a symlink, you'll see it's identified as a link and points to the original path.
Which of the following commands would list the files image_1.jpg, image_3.jpg, and image_5.jpg, but NOT image_2.jpg or image_10.jpg?
When is it more appropriate to use the find command instead of shell globbing (e.g., *)?
With these tools, you can move beyond simple file listing and perform complex, automated operations with precision and efficiency.