ARCHIVED: In Unix, how do I rename *.foo to *.bar, or change filenames to lowercase?
In Unix, if you are attempting to change the extension for
multiple files, you may be tempted to try the command mv
*.foo *.bar
thinking that this will move each file ending in
.foo
to a new file ending in .bar
.
When considering why this command does not work, think about how the
shell
expands wildcards. Before the mv
command ever sees the
arguments, *.foo
and *.bar
are expanded.
Depending on your shell, this can fail in a couple of ways. The
csh
shell prints "No match", because it can't match
*.bar
. The sh
shell 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 accomplish this 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 or Korn 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
similar to renaming foo.*
to bar.*
,
you can use a command such as sed
to strip apart the
original filename in other ways, but the general looping idea is the
same. You can also convert filenames into mv
commands
with sed
, and hand the commands off to
sh
for execution. Try the following:
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 the following:
mmv '*.foo' '=1.bar'
You can use shell loops like the above to translate filenames from upper- to lowercase or vice versa. 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 wish to be extremely thorough and handle files with unusual names (e.g., embedded blanks) 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 (e.g.,
\c
).
If you have the Perl language installed, you may find this rename script by Larry Wall very useful; you can use it 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 $_; }
At Indiana University, for personal or departmental Linux or Unix systems support, see Get help for Linux or Unix at IU.
Related documents
This is document abec in the Knowledge Base.
Last modified on 2018-01-18 09:23:10.