Unix How-To: Tricks for Working with Filenames

In this week's column, I answer two readers' questions about working with Unix filenames. One asks how to easily remove all files in a directory except those that match a particular pattern. The other asks how to force the names of files to be all lowercase. The answers may be easier than you think.

[ See also: Unix Commands to Try When You're Bored ]

A reader recently asked me "How do I remove all files in a directory except those that end in a particular suffix, such as .c?". Not hard given a little Unix know how, but there are several ways to exempt files from your Unix commands. The first trick that comes to mind is using the find command with its special not (!) operator. For example, the command "find . ! -name *.c" would find all the files you want to remove. You could use this in a command like this provided you want to do the same with subdirectories or don't have any:

$ find . -type f ! -name *.c -exec rm {} \;

I threw in the "-type f" clause to ensure that the command would not try to remove directories and generate errors. If you don't want the file removing operation to work on subdirectories, you can stop it using the -maxdepth option. With a maxdepth of 1, the find command will only work in the current directory.

$ find . -maxdepth 1 ! -name "*.c" -print -exec rm {} \;

A lot of people prefer piping the output of a find command to xargs to using the -exec rm option, but the rm command will complain if it isn't provided with files to remove. Depending on how and when you'll be using the command, you might not want to risk the errors. Another option is simply to move all the files you want to preserve to a temporary directory, clean out the current directory and then move the preserved files back into place. This solution will remove subdirectories as well if you use "rm -r" or will leave them intact, depending on the options you use to clean out the unwanted files.

$ mkdir ~/tmp$$
$ mv *.c ~/tmp$$
$ rm -r *
$ mv ~/tmp$$/* .
$ rmdir ~/tmp$$

Another reader asked how she could conveniently rename files with uppercase characters in their names to be all lowercase. While tricks with sed and tr are possible, using the typeset command to force a variable to be lowercase makes quick work of this problem. I sent her this script:

# rename files to be all lowercase

# NOTE: typeset defines $l as lowercase
typeset -l l

for u in [A-Z]*
   mv $u $l

I used $u (for uppercase) and $l (for lowercase) to make the script a little easier to read. The use of the typescript command avoids any need to map A-Z to a-z in some form of regular expression.

More Unix Tips

This article is published as part of the IDG Contributor Network. Want to Join?

Computerworld's IT Salary Survey 2017 results
Shop Tech Products at Amazon