tags:

views:

521

answers:

9

Say I have three files (template_*.txt):

  • template_x.txt
  • template_y.txt
  • template_z.txt

I want to copy them to three new files (foo_*.txt).

  • foo_x.txt
  • foo_y.txt
  • foo_z.txt

Is there some simple way to do that with one command, e.g.

cp --enableAwesomeness template_*.txt foo_*.txt

A: 

I don't know of anything in bash or on cp, but there are simple ways to do this sort of thing using (for example) a perl script:

($op = shift) || die "Usage: rename perlexpr [filenames]\n";

for (@ARGV) {
    $was = $_;
    eval $op;
    die $@ if $@;
    rename($was,$_) unless $was eq $_;
}

Then:

rename s/template/foo/ *.txt
Blair Conrad
+1  A: 
for i in template_*.txt; do cp -v "$i" "`echo $i | sed 's%^template_%foo_%'`"; done

Probably breaks if your filenames have funky characters in them. Remove the '-v' when (if) you get confidence that it works reliably.

pauldoo
+2  A: 

This should work:

for file in template_*.txt ; do cp $file `echo $file | sed 's/template_\(.*\)/foo_\1/'` ; done
Chris Bartow
+3  A: 
[01:22 PM] matt@Lunchbox:~/tmp/ba$
ls
template_x.txt  template_y.txt  template_z.txt

[01:22 PM] matt@Lunchbox:~/tmp/ba$
for i in template_*.txt ; do mv $i foo${i:8}; done

[01:22 PM] matt@Lunchbox:~/tmp/ba$
ls
foo_x.txt  foo_y.txt  foo_z.txt
Matt McMinn
+11  A: 
for f in template_*.txt; do cp $f foo_${f#template_}; done
Chris Conway
+1  A: 

@Chris Conway's answer is good, and I wish I'd remembered ${f#...} when I was writing my other answer, but it'll break down if you need to do something more sophisticated than replace text at the beginning (or end) of the filename. Of course, if that's all the complexity you need, great!

Blair Conrad
A: 

Yet another way to do it:

$ ls template_*.txt | sed -e 's/^template\(.*\)$/cp template\1 foo\1/' | ksh -sx

I've always been impressed with the ImageMagick convert program that does what you expect with image formats:

$ convert rose.jpg rose.png

It has a sister program that allows batch conversions:

$ mogrify -format png *.jpg

Obviously these are limited to image conversions, but they have interesting command line interfaces.

Jon Ericson
+1  A: 

The command mmv (available in Debian or Fink or easy to compile yourself) was created precisely for this task. With the plain Bash solution, I always have to look up the documentation about variable expansion. But mmv is much simpler to use, quite close to "awesomeness"! ;-)

Your example would be:

mcp "template_*.txt" "foo_#1.txt"

mmv can handle more complex patterns as well and it has some sanity checks, for example, it will make sure none of the files in the destination set appear in the source set (so you can't accidentally overwrite files).

Bruno De Fraine
+3  A: 

My preferred way:

for f in template_*.txt; do cp $f ${f/template/foo}; done

The "I-don't-remember-the-substitution-syntax" way:

for i in x y z; do cp template_$i foo_$i; done
Roberto Bonvallet