Title: How do I rename files using wildcards ala the DOS "REN" command? Question: I have a bunch of files on my Saul account with the extension "txt" that I would like to rename with the extension "sgl". In DOS you would use the following command: REN *.txt *.sgl But the Unix command I've been told to use for renaming files, the "mv" command, seems to get weird on wildcards and doesn't work. That is... mv *.txt *.sgl ...does not work the way the REN command does under DOS. Answer: Unix commands for the most part work very differently than DOS or VMS commands. The underlying operating systems themselves are totally different (Unix being much more capable and powerful than DOS by a long shot, and much more flexible than VMS). Many DOS and VMS users new to Unix fall into the same trap with wildcards. The answer given here is a summary of about four chapters of a "how to use Unix" book. There are a lot of powerful features of Unix shells and commands that I will mention. When trying to learn a new operating system, you really need to expect to spend some time reading some books and the documentation for commands to pick things up. This is just as true for when you learned DOS, so I hope you aren't upset about this statement. A good "how to" book to read is: Student's Guide to Unix, Harley Hahn (McGraw-Hill, 1990, ISBN 0-07-025511-3) Briefly, the DOS shell is pretty much brain dead and limited to a puny 124 character command line (or something like that), so all DOS commands must do their own wildcard processing. The DOS shell (COMMAND.COM) doesn't even know what a wildcard character is. This means that when the REN command sees the two strings "*.txt" and "*.sgl", it is coded to know this means "find all files that end with the extension .TXT and rename them so the extension is now .SGL". This is specific to the REN command (other commands may behave differently, or not accept wildcards at all, like MORE I believe). If you don't like the "brain dead" label, try doing this wildcard in some DOS commands and see what you get: *a.txt (most commands don't even see the "a" and just think you mean *.txt--two very different sets of files). In Unix, the shell command line length is much longer (usually more than 4096 characters) and shells have the concept of "wildcards" that really mean "find any characters that match, expand them into the command line, then try parsing the command line again." Once file names are expanded, the shell passes the entire command line to the program you wish to run. The man pages for commands tell what they accept. If you check the man page for "mv" (which you should whenever you want to learn what arguments and options a given command accepts, and how it will deal with them) you will see: Name mv - move or rename files Syntax mv [-i] [-f] [-] file1 file2 mv [-i] [-f] [-] file... directory Description The mv command moves (changes the name of) file1 to file2. If file2 already exists, it is removed before file1 is moved. If file2 has a mode which forbids writing, mv prints the mode and reads the standard input to obtain a line. If the line begins with y, the move takes place. If it does not, mv exits. For further information, see chmod(2). In the second form, one or more files (plain files or directories) are moved to the directory with their original file-names. Given the (admittedly brief) description of how the shell interprets wildcards, what you have told the shell is to expand file names in the current working directory that match the names "*.txt" and "*.sgl". You either will or won't have any files named "*.sgl", and the last one may or may not be a directory. If there are no such files, you have told "mv" to move all the files with names that end with ".txt" into a non-existent directory named "*.sgl", which will fail because there isn't a directory. If there was a file that ended with ".sgl", then you are telling "mv" to move a list of files to the directory whose name is the last file named ".sgl", which will also fail because it isn't a directory. That's the long story. So there must be something more to it, right? Yes. Since "mv" wants you to give two names--the name of the file to rename, and the new name you want it to have--you will need to execute the "mv" command once for each file. "What a pain in the ..." you say. Well, Unix shells have much more powerful iterative commands than do DOS or VMS, so all you need to know is that if you use the C shell (which is most likely your login shell, unless you've changed it) you can use the "foreach" command. "How does 'foreach' work?" you say. The short answer is: % foreach file (*.txt) > echo $file > end 1.txt 2.txt 3.txt (Note: this example shows what you type at the command line, but I don't show the carriage returns at the end of each line; just the prompts "%" and ">". Type the "foreach ..." and "echo ..." stuff at the command line, and if you have files named "1.txt 2.txt 3.txt" you will see the same thing I show above.) Is there another command that one would use to do a multiple-file renaming under Unix, or am I doing something wrong? There is one more step. You need to remove the ".txt" extension and insert the ".sgl" extension in the "mv" command. This is done with another powerful feature of Unix shells, called "in-line command substitution". The command to strip off file extensions is "basename" (see "man basename"). To do in-line command substitution, use the "back-tick" character; the single quote that leans to the left: ` Use "echo" to see how this works: % echo *.txt 1.txt 2.txt 3.txt <== see the files named ".txt" % echo `basename 1.txt .txt` 1 <== the ".txt" is stripped off % ls *.sgl No match <== there are no ".sgl" files % mv 1.txt `basename 1.txt .txt`.sgl % ls *.sgl 1.sgl <== now there is The command sequence is then: % foreach file (*.txt) > mv $file `basename $file .txt`.sgl > end Don't put any spaces between the last back-tick and the ".sgl", since a space would mean you wanted to rename everything into the directory ".sgl", which probably doesn't exist. This may look kind of complicated, but it is really pretty simple. Instead of just removing the ".txt", I could have taken all files with names like "foo1234-bar.txt" and changed them to be "BAR.1234-foo.sgl" by matching on the letters, numbers, and dashes. Let's see DOS do that! Date: 7/96 Author: Dittrich