Prerequisites:
o Familiarity with the bash shell
o Familiarity with the find command
o Beginner's knowledge of what an inode is |
I've often ranted about what I consider to be a lack of competency in the IT field. I blame much of this on the interview process--it's difficult to assess a candidate's skill by simply asking questions. Having a candidate sit down in front of a laptop and try to solve an actual problem instead can be much more useful. Below is one of many lab exercises I use.
Listing 1:
Problem: You are tasked with removing the following files.
You must remove each file individually.
Neptune:/tmp/example3 # ls -lrat
total 12
drwxrwxrwt 11 root root 8192 Mar 22 12:50 ..
-rw-r--r-- 1 dranok users 0 Mar 22 12:51 -this-file-starts-with-a-dash
-rw-r--r-- 1 dranok users 0 Mar 22 12:51 数独」
-rw-r--r-- 1 dranok users 0 Mar 22 12:52 how many spaces
-rw-r--r-- 1 dranok users 0 Mar 22 12:52 immutable
drwxr-xr-x 2 dranok users 4096 Mar 22 12:52 . |
I say each file must be removed individually because in real-life scenarios you're not going to be able to rm -rf the entire directory. In fact, this is a dangerous idea when you have files with strange characters--you may end up deleting something important. Further, there may be files in the directory you need to keep. Besides, running rm -rf on the folder won't always work.
I like this example because each of these files is increasingly difficult to remove.
Most people try to remove the immutable file first. They get the following error, even as root.
Listing 2:
Neptune:/tmp/example3 # rm immutable
rm: remove write-protected regular empty file `immutable'? y
rm: cannot remove `immutable': Operation not permitted |
Nope, this isn't an NFS share. so why can't root delete this file? We'll come back to this one.
The "how many spaces" file (which starts with a number of spaces) is the easiest to remove. Just use a wildcard and this one is simple:
Listing 3:
Neptune:/tmp/example3 # rm *how*
Neptune:/tmp/example3 # ls -lrat
total 12
-rw-r--r-- 1 dranok users 0 Mar 22 12:51 -this-file-starts-with-a-dash
-rw-r--r-- 1 dranok users 0 Mar 22 12:51 数独」
-rw-r--r-- 1 dranok users 0 Mar 22 12:52 immutable
drwxrwxrwt 11 root root 8192 Mar 22 13:00 ..
drwxr-xr-x 2 dranok users 4096 Mar 22 13:04 . |
The next easiest is the "-this-file-starts-with-a-dash" file. Most people tend to struggle with this one.
Listing 4:
Neptune:/tmp/example3 # rm -this-file-starts-with-a-dash
rm: invalid option -- t
Try `rm ./-this-file-starts-with-a-dash' to remove the file
Try `rm --help' for more information.
Neptune:/tmp/example3 # rm *dash
rm: invalid option -- t
Try `rm ./-this-file-starts-with-a-dash' to remove the file
Try `rm --help' for more information. |
Even wildcards won't work here. The problem is that rm is interpreting the dash as an argument. The easiest answer is to remember that modern Linux commands use getopt, and that two dashes means "end of options":
Listing 5:
Neptune:/tmp/example3 # rm -- *dash
Neptune:/tmp/example3 # ls -lrat
total 12
-rw-r--r-- 1 dranok users 0 Mar 22 12:51 数独」
-rw-r--r-- 1 dranok users 0 Mar 22 12:52 immutable
drwxrwxrwt 11 root root 8192 Mar 22 13:00 ..
drwxr-xr-x 2 dranok users 4096 Mar 22 13:08 . |
Next we'll tackle the file that contains kanji (数独」). If your terminal (or web browser) doesn't have the Japanese fonts installed this likely shows up as a series of boxes. How do you selectively remove this file?
The answer is to delete the file via its inode. Among other things, an inode is a unique numerical ID for every file on your filesystem.
To see these inode values, use "ls -li":
Listing 6:
Neptune:/tmp/example3 # ls -li
total 0
2573051 -rw-r--r-- 1 dranok users 0 Mar 22 12:52 immutable
2573049 -rw-r--r-- 1 dranok users 0 Mar 22 12:51 数独」 |
Now we know the inode is 2573049. To remove it, we invoke the find command:
Listing 7:
Neptune:/tmp/example3 # find . -maxdepth 1 -inum 2573049 -ok rm {} \;
< rm ... ./数独」 > ? y
Neptune:/tmp/example3 # ls -lrat
total 12
-rw-r--r-- 1 dranok users 0 Mar 22 12:52 immutable
drwxrwxrwt 12 root root 8192 Mar 22 13:12 ..
drwxr-xr-x 2 dranok users 4096 Mar 22 13:13 . |
Easy enough. We use "-ok" here instead of "-exec" since "-ok" will prompt us before running the command. Removing files with strange characters can be dangerous so it's always a good idea to take precautions. We used "-maxdepth 1" to ensure find wouldn't recurse into subdirectories.
That leaves us with that "immutable" file. At this point, even trying to "rm -rf" the directory will fail:
Listing 8:
Neptune:/tmp # rm -rf example3
rm: cannot remove `example3/immutable': Operation not permitted |
The first thing to check when root cannot delete a local (non-NFS) file is the extended filesystem attributes. This can be achieved with the "lsattr" command:
Listing 9:
Neptune:/tmp/example3 # lsattr
----i-------- ./immutable |
The "i" in the series of dashes means this file is immutable, or write-protected. To remove this flag from the file you must use the change attribute command, chattr:
Listing 10:
Neptune:/tmp/example3 # chattr -i immutable
Neptune:/tmp/example3 # lsattr
------------- ./immutable
Neptune:/tmp/example3 # rm immutable
Neptune:/tmp/example3 # ls -lrat
total 12
drwxrwxrwt 12 root root 8192 Mar 22 13:15 ..
drwxr-xr-x 2 dranok users 4096 Mar 22 13:18 . |
Congratulations! All the files have been removed.
Extended ext2/ext3 file attributes are very useful, however they are outside the scope of this article. Links are provided at the end of this article for more information.
See Also: