user001
user001

Reputation: 1848

change *.foo to *.bar in unix one-liner

I am trying to convert all files in a given directory with suffix ".foo" to files containing the same basename but with suffix modified to ".bar". I am able to do this with a shell script and a for loop, but I want to write a one-liner that will achieve the same goal.

Objective:
  Input: *.foo
  Output: *.bar

This is what I have tried:

find . -name "*.foo" | xargs -I {} mv {} `basename {} ".foo"`.bar

This is close but incorrect. Results:
  Input: *.foo
  Output: *.foo.bar

Any ideas on why the given suffix is not being recognized by basename? The quotes around ".foo" are dispensable and the results are the same if they are omitted.

Upvotes: 4

Views: 1657

Answers (6)

Kidzor
Kidzor

Reputation: 1

Why don't you use "rename" instead of scripts or loops.

RHEL: rename foo bar .*foo

Debian: rename 's/foo/bar/' *.foo

Upvotes: -1

evil otto
evil otto

Reputation: 10582

Although basename can work on file extensions, using the shell parameter expansion features is easier:

for file in *.foo; do mv "$file" "${file%.foo}.bar"; done

Your code with basename doesn't work because the basename is only run once, and then xargs just sees {}.bar each time.

Upvotes: 4

glglgl
glglgl

Reputation: 91109

If you have installed mmv, you can do

mmv \*.foo \#1.bar

.

Upvotes: -1

Maxim Egorushkin
Maxim Egorushkin

Reputation: 136425

$ for f in *.foo; do echo mv $f ${f%foo}bar; done
mv a.foo a.bar
mv b.foo b.bar

Remove echo when ready.

Upvotes: 1

Steve B.
Steve B.

Reputation: 57325

for x in $(find . -name "*.foo"); do mv $x ${x%%foo}bar; done

Upvotes: 1

hari
hari

Reputation: 9733

for file in *.foo ; do mv $file echo $file | sed 's/\(.*\.\)foo/\1bar/' ; done

Example:

$ ls
1.foo  2.foo
$ for file in *.foo ; do mv $file `echo $file | sed 's/\(.*\.\)foo/\1bar/'` ; done
$ ls
1.bar  2.bar
$ 

Upvotes: 2

Related Questions