Looks like no one’s replied in a while. To start the conversation again, simply ask a new question.

Terminal command to rename files in bulk with wild cards?

I had a group of files that had double extensions in the name and I wanted to strip the second extension:

myfile.r01.1
myfile.r02.1

so that the new names were

myfile.r01
myfile.r02

In DOS this would be accomplished easily by using the command line:

rename myfile.r??.1 myfile.r??

In OS X Terminal/Bash shell, though I couldn't find a command that has similar function that allows the use of wild cards in the file names.

I tried both the 'mv' abd 'cp' commands along the lines of:

mv myfile.r??.1 myfile.r??

but nothing worked, even using the * for the wildcard.

I did manage to use the Automator to accomplish the task by using some of its Finder options, but really, a simple command line would have been simpler and easier than building an Automator workflow for this.

Can anyone point me to a unix command that would have done what I am looking for, and the proper syntax for it?

Thanks.

Mac Pro 4gb, dual 23" Cinema Display, Mac OS X (10.4.9), MacBook Pro 15" 60gb Video iPod 8gb iPhone

Posted on Mar 20, 2008 2:33 PM

Reply
Question marked as Best reply

Posted on Mar 20, 2008 2:41 PM

You'll get a bunch of answers on how to do this, using foreach loops and various perl scripts.

In zsh, which should be the OS X default shell, this is very easy.

To start zsh, just type "zsh"

To make it your default shell, just issue "chsh -s /bin/zsh"

Once you are in zsh, you need do only two things (which you can put in your ~/.zshrc file for safe-keeping and automation):


autoload -U zmv
alias mmv="noglob zmv -W"


Now you have a simple command to do as you want:


mmv myfile.*.1 myfile.*


I suspect


mmv myfile.r??.1 myfile.r??


does the same thing. The ? is a wildcard for a single space.

You can call "mmv" anything you want, like "rename".
12 replies
Question marked as Best reply

Mar 20, 2008 2:41 PM in response to DSA1

You'll get a bunch of answers on how to do this, using foreach loops and various perl scripts.

In zsh, which should be the OS X default shell, this is very easy.

To start zsh, just type "zsh"

To make it your default shell, just issue "chsh -s /bin/zsh"

Once you are in zsh, you need do only two things (which you can put in your ~/.zshrc file for safe-keeping and automation):


autoload -U zmv
alias mmv="noglob zmv -W"


Now you have a simple command to do as you want:


mmv myfile.*.1 myfile.*


I suspect


mmv myfile.r??.1 myfile.r??


does the same thing. The ? is a wildcard for a single space.

You can call "mmv" anything you want, like "rename".

Mar 20, 2008 6:46 PM in response to DSA1

I like to use awk to build a list of commands. When it looks ok, I feed it to bash:
<pre style="padding-left: .75ex; padding-top: .25em; padding-bottom: .25em; margin-top: .5em; margin-bottom: .5em; margin-left: 1ex; max-width: 80ex; overflow: auto; font-size: 9px; font-family: Monaco, 'Courier New', Courier, monospace; color: #222; background: #ddd; line-height: normal">ls | awk '{org=$0; sub(/\.[^\.]*$/,""); printf("mv %s %s\n", org, $0);}'
mv myfile.r01.1 myfile.r01
mv myfile.r02.1 myfile.r02
</pre>

If you like that, pipe it sh:
<pre style="padding-left: .75ex; padding-top: .25em; padding-bottom: .25em; margin-top: .5em; margin-bottom: .5em; margin-left: 1ex; max-width: 80ex; overflow: auto; font-size: 9px; font-family: Monaco, 'Courier New', Courier, monospace; color: #222; background: #ddd; line-height: normal">ls | awk '{org=$0; sub(/\.[^\.]*$/,""); printf("mv %s %s\n", org, $0);}' | sh
</pre>
--
Cole

Mar 20, 2008 6:59 PM in response to DSA1

Bill Scott wrote:
You'll get a bunch of answers on how to do this, using foreach loops and various perl scripts.


Actually, I wouldn't even bother that much. I would just get a directory listing, put it into a text file, do global search and replace to construct "mv" statements, then "sh" my text file.

In zsh, which should be the OS X default shell, this is very easy.

To start zsh, just type "zsh"

To make it your default shell, just issue "chsh -s /bin/zsh"


To be fair to other shells, you don't have to make zsh your default shell to use it.


autoload -U zmv
alias mmv="noglob zmv -W"


Bill,
Would you be kind enough to explain what all that does?

Cole,
You don't need to bother. Awk is way over my head. 🙂

Mar 21, 2008 5:40 AM in response to Bill Scott

If you want the solution is one command the zsh solution may be the easiest.

The best answer is a matter of preference.
Bill's right though about the thousands of 3-4 command possibilities with loops depending on which shell is used. The fact is regular expressions in UNIX are so powerful that many prefer that to a simple replace. Others may not want to get that technical.

Here is a solution using a for loop in sh, ksh, or bash

for file in myfile.r??.1
do
base=`basename $file .1`
mv $file $base
done

The for or foreach loop depending on shell will cycle through each string matching the regular expression.

basename is a command that removes the directory path and the specified regular expression suffix from any string. Each shell has additional similar constructs for manipulating any string in any way in one word.

Mar 21, 2008 5:40 AM in response to etresoft

To be fair to other shells, you don't have to make zsh your default shell to use it.


To be fair, I wrote just that.

Would you be kind enough to explain what all that does?


zsh comes with a bunch of functions that live in /usr/share/zsh/4.3.4/functions

The first line loads the function /usr/share/zsh/4.3.4/functions/zmv

The second line creates an alias to make that function (when invoked via the alias) behave in a way that is consistent with the "rename" command he was asking about.

Read the top of the zmv function file (it is a shell script) if you want the details.

Mar 21, 2008 8:59 AM in response to DSA1

From this page: http://www.faqs.org/faqs/unix-faq/faq/part2/section-6.html


How do I rename "*.foo" to "*.bar", or change file names to lowercase?

Why doesn't "mv *.foo *.bar" work? Think about how the shell
expands wildcards. "*.foo" and "*.bar" are expanded before the
mv command ever sees the arguments. Depending on your shell,
this can fail in a couple of ways. CSH prints "No match."
because it can't match "*.bar". SH executes "mv a.foo b.foo
c.foo *.bar", which will only succeed if you happen to have a
single directory named "*.bar", which is very unlikely and almost
certainly not what you had in mind.
Depending on your shell, you can do it with a loop to "mv" each
file individually. If your system has "basename", you can use:
C Shell:
foreach f ( *.foo )
set base=`basename $f .foo`
mv $f $base.bar
end
Bourne Shell:
for f in *.foo; do
base=`basename $f .foo`
mv $f $base.bar
done
Some shells have their own variable substitution features, so
instead of using "basename", you can use simpler loops like:
C Shell:
foreach f ( *.foo )
mv $f $f:r.bar
end
Korn Shell:
for f in *.foo; do
mv $f ${f%foo}bar
done
If you don't have "basename" or want to do something like
renaming foo.* to bar.*, you can use something like "sed" to
strip apart the original file name in other ways, but the general
looping idea is the same. You can also convert file names into
"mv" commands with 'sed', and hand the commands off to "sh" for
execution. Try
ls -d *.foo | sed -e 's/.*/mv & &/' -e 's/foo$/bar/' | sh
A program by Vladimir Lanin called "mmv" that does this job
nicely was posted to comp.sources.unix (Volume 21, issues 87 and
88) in April 1990. It lets you use
mmv '*.foo' '=1.bar'
Shell loops like the above can also be used to translate file
names from upper to lower case or vice versa. You could use
something like this to rename uppercase files to lowercase:
C Shell:
foreach f ( * )
mv $f `echo $f | tr '[A-Z]' '[a-z]'`
end
Bourne Shell:
for f in *; do
mv $f `echo $f | tr '[A-Z]' '[a-z]'`
done
Korn Shell:
typeset -l l
for f in *; do
l="$f"
mv $f $l
done
If you wanted to be really thorough and handle files with `funny'
names (embedded blanks or whatever) you'd need to use
Bourne Shell:
for f in *; do
g=`expr "xxx$f" : 'xxx(.*)' | tr '[A-Z]' '[a-z]'`
mv "$f" "$g"
done
The `expr' command will always print the filename, even if it
equals `-n' or if it contains a System V escape sequence like `c'.
Some versions of "tr" require the [ and ], some don't. It
happens to be harmless to include them in this particular
example; versions of tr that don't want the [] will conveniently
think they are supposed to translate '[' to '[' and ']' to ']'.
If you have the "perl" language installed, you may find this
rename script by Larry Wall very useful. It can be used to
accomplish a wide variety of filename changes.
#!/usr/bin/perl
#
# rename script examples from lwall:
# rename 's/.orig$//' *.orig
# rename 'y/A-Z/a-z/ unless /^Make/' *
# rename '$_ .= ".bad"' *.f
# rename 'print "$_: "; s/foo/bar/ if <stdin> =~ /^y/i' *
$op = shift;
for (@ARGV) {
$was = $_;
eval $op;
die $@ if $@;
rename($was,$_) unless $was eq $_;
}

Mar 24, 2008 4:38 PM in response to DSA1

All-

Several comprehensive answers. As I said in my original post, I did accomplish it with Automator replace text command, but I will try each of these as a learning experience. I am surprised that there's nothing as simple as the DOS solution to this type of task.

Thanks again.

Mar 25, 2008 6:07 AM in response to Bill Scott

Bill Scott wrote:
I don't have access to dos, but am willing to bet what they call rename is that perl script Larry Wall wrote (syntax changed for dos).


RENAME (REN) is an internal command of DOS's terminal. I don't know what it does under the hood, and DOS pre-dates perl by a few years, but I don't recall if the REN command was there from the beginning or not. Knowing microsoft's reputation for stealing other's work, wouldn't be surprised either way if their internal command came from them or someone else.

Terminal command to rename files in bulk with wild cards?

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple ID.