Chapter 5: Working with Text Files
Most Linux configuration is done by editing plain text files. Whether you’re modifying files in the /etc directory to configure local services or editing Ansible playbooks to manage hosts, plain text files are everywhere in these tasks.
5.1 Editing Files with vim and vi
vim is an improved version of vi. They work similarly, but vim includes features like tutorials and syntax highlighting. I recommend using vim.
In fact, in many Linux distributions, vi is just an alias for vim. Running alias vi usually outputs alias vi='vim', though the root user often doesn’t have this alias set.
Other text editors exist in Linux, such as nano, gedit, jed, joe, kate, kedit, mcedit, and nedit. Among these, jed and joe are common for plain text.
5.1.1 Getting Started with vi
vi has three modes: the primary ones are Command Mode and Input Mode, plus Ex Mode. By default, you enter a file in Command Mode (after running the vi file command).
Command Mode means you need to enter a command (one or two letters, sometimes with optional numeric parameters) to tell vi what you want to do before you can change any text.
Note: Commands are case-sensitive.
- Adding Text
To enter Input Mode, type an input command letter.
| Command | Description |
|---|---|
| a | Append command. Enter text to the right of the cursor. |
| A | Append at the end of the line. Start entering text at the end. |
| i | Insert command. Enter text to the left of the cursor. |
| I | Insert at the beginning of the line. Start at the start of the line. |
| o | Open below. Open a new line below the current one and enter Insert Mode. |
| O | Open above. Insert a new line above the current one and enter Insert Mode. |
Once in Insert Mode, --INSERT-- will appear at the bottom of the screen.
After finishing your input, press Esc to return to Command Mode (sometimes you might need to press it twice).
- Moving in Text
Use these keys to move a single character:
| Key | Description |
|---|---|
| Arrow Keys | Up, Down, Left, Right |
| h, j, k, l | Left, Down, Up, Right |
| Backspace, Space | Left, Right |
Commands for moving multiple characters:
| Command | Description |
|---|---|
| w | Move to the start of the next word (separated by space, tab, or punctuation). |
| W | Move to the start of the next word (separated by space or tab). |
| b | Move to the start of the previous word (space, tab, or punctuation). |
| B | Move to the start of the previous word (space or tab). |
| 0 (zero) | Move to the start of the current line. |
| $ | Move to the end of the current line. |
| H | Move to the top-left of the screen (first line on screen). |
| M | Move to the first character of the middle line on the screen. |
| L | Move to the bottom-left of the screen (last line on screen). |
- Deleting, Copying, and Changing Text
These commands can be combined with movement keys (arrows, PgUp, PgDn, letters) and numbers to specify exactly what to delete, copy, or change.
| Command | Description |
|---|---|
| x | Delete character under cursor |
| X | Delete character before cursor |
| d | Delete some text |
| c | Change some text |
| y | Copy (yank) some text |
The <?> after each command represents the movement command used, for example:
dw— Delete one word after the cursor.db— Delete one word before the cursor.dd— Delete the entire current line.c$— Change from the current character to the end of the line (deletes then enters Input Mode).c0— Change from the character before the cursor to the start of the line.cl— Delete current character and enter Input Mode.cc— Delete current line and enter Input Mode.yy— Copy the current line to the buffer.y)— Copy the sentence to the right of the cursor to the buffer.y}— Copy the paragraph to the right of the cursor to the buffer.
You can also use numbers to modify these commands:
3dd— Delete 3 lines starting from the current line.3dw— Delete the next 3 words.5cl— Change the next 5 characters.12j— Move down 12 lines.5cw— Delete the next 5 words and enter Input Mode.4y)— Copy the next 4 sentences.
- Pasting (Placing) Text
Place the last text stored in the buffer into the file.
| Command | Description |
|---|---|
| P | Paste to the left of the cursor; if a full line, paste above. |
| p | Paste to the right of the cursor; if a full line, paste below. |
- Repeating Commands
After deleting, changing, or pasting text, use . to repeat the action. For example, after replacing “Joe” with “Jim” (cw), find the next occurrence and press . to repeat the change.
- Exiting vi
In Command Mode, use ZZ to save and exit. Alternatively, press : to enter Ex Mode.
| Command | Description |
|---|---|
| :w | Save the current file without exiting. |
| :wq | Save and exit (same as ZZ). |
| :q | Exit, but only works if no changes were made. |
| :q! | Force exit without saving changes. |
- Other Commands
u— Undo changes.Ctrl+R— Redo (undoes the previous undo).:!command– Run a shell command directly after:!, e.g.,:!dateto see the current date. You can even use:!bashto start a new shell, but it’s better to save your work first.Ctrl+g— Displays the filename, current line number, total lines, percentage of file content, and current column.
5.1.2 Navigating Through Files
If the file is long, use these methods to move faster:
| Command | Description |
|---|---|
| Ctrl+f | Page forward one full screen. |
| Ctrl+b | Page backward one full screen. |
| Ctrl+d | Scroll forward half a screen. |
| Ctrl+u | Scroll backward half a screen. |
| G | Go to the last line of the file. |
| nG | Go to line n. |
5.1.3 Searching Text
Search forward or backward using / and ?. You can also use metacharacters:
/hello*— Search forward for lines starting with “hello”.?[pP]rint— Search backward for “print” or “Print”.
After starting a search, use n or N to search in the same or opposite direction.
5.1.4 Using Ex Mode
The vi editor was originally based on the ex editor. While it doesn’t work in full-screen mode, you can use Ex Mode commands to find and change text on one or more lines.
Enter Ex Mode from Command Mode using ::
:g/Local— Search for the word “Local” and print the relevant lines.:s/Local/Remote— Replace the first occurrence of “Local” with “Remote” on the current line.:g/Local/s//Remote— Replace the first “Local” on every line with “Remote”.:g/Local/s//Remote/g— Replace every “Local” in the file with “Remote”.:g/Local/s//Remote/gp— Replace every “Local” in the file and print each affected line.
5.1.5 Learning More
Run vimtutor to open a built-in tutorial in the vim editor.
5.2 Finding Files
Use these commands to help locate files on your system:
locate— Find files by name.find— Find files based on various attributes.grep— Search for specific text inside files.
5.2.1 Using locate to Find Files by Name
Most Linux systems run the updatedb command daily to index filenames into a database. The locate command searches this database. You can manually update it with sudo updatedb. You can only see files that your user has permission to access via locate.
locate [str] or locate -i [str] to ignore case. For example, to search for directories containing “yexca” regardless of case: locate -i yexca.
Note: Not all files are indexed; the /etc/updatedb.conf file determines which files are excluded from the database.
5.2.2 Using find to Search for Files
find is the most powerful command for searching the filesystem. It can find files based on attributes (metadata) and perform actions on the results.
Note: File metadata includes owner, group, timestamps, size, permissions, and other info stored in the inode.
find vs locate
findsearches the actual filesystem, so it’s slower thanlocate, but it provides real-time results (whereaslocatemight miss new files). When usingfind, specify a starting point to limit the scope and improve speed.
The find command has a special -ls option that lists detailed file info, similar to ls -l.
Note: Regular users will see many errors due to permissions. You can redirect errors to /dev/null by adding 2>/dev/null to the end of the command.
- Finding files by name
Use -name and -iname (case-insensitive) for filenames. You can use wildcards (* and ?):
| |
This searches /etc for files containing “passwd” (case-insensitive). If no directory is specified, it searches the current folder.
Use the -type option to filter by files (-type f) or directories (-type d).
- Finding files by size
Use the -size option with + or - prefixes. For example, find /etc -size +10M finds files in /etc larger than 10MB.
| |
This finds files between 500MB and 5GB in /bigdata and runs du on each to show their size.
- Finding files by user
Use -user or -group. You can combine these with -not and -or.
| |
Finds files in /home owned by either yexca or lemon.
- Finding files by permissions
Use the -perm option with numeric or symbolic modes.
-perm -777: Matches if at least all three bits are set.-perm /777(or+777in older versions): Matches if any of the bits are set.-perm 777: Exact match.
find -perm /002 finds files that are writable by “others,” regardless of other permissions.
- Finding files by date and time
Time options (-atime, -ctime, -mtime) search based on days since access, change, or metadata modification. Minute options (-amin, -cmin, -mmin) do the same for minutes.
Prefix the value with - for “less than” (from now until then) and + for “more than” (further back in time).
- Changes in the last 10 minutes:
| |
- Permission changes in the last three days:
| |
- Files not accessed for over 300 days:
| |
- Using ’not’ and ‘or’ logic
- Owned by
yexcabut not in theyexcagroup:
| |
- Owned by
yexcaAND larger than 1GB:
| |
- Executing commands on found files
Use -exec to run a command on every match without confirmation, or -ok to ask for confirmation first. The syntax is:
| |
{} represents the found filename. The command must end with \;.
| |
5.2.3 Using grep to Search Inside Files
grep searches for specific text strings within files. It can print the matching lines or just the filenames. grep also works with standard output.
| Option | Description |
|---|---|
| -i | Ignore case. |
| -v | Search for lines NOT containing the text. |
| -r | Search directories recursively. |
| -l | Show only the names of matching files. |
| –color | Highlight the matching text (usually in red). |
- Recursively search for “root” in
/etc/sysconfig:
| |
- Search for “inet” in the output of a command:
| |