Computing.Net > Forums > Linux > Shell Script to rename files

Computer Problems? Computing.Net has over 1,000,000 posts about all things technology related! Over 90% answered within 24 hours! Click here to start participating now! Also, be sure to check out the New User Guide.

Shell Script to rename files

Reply to Message Icon

Name: bobpaul
Date: November 30, 2005 at 18:48:53 Pacific
OS: Gentoo
CPU/Ram: 2.4Ghz Barton + 1GB
Comment:

I have a bunch of files in one of three forms

This: "word.word.A#A##.word.word.foo"
or: "word.word.###.word.word.foo"
or: "### - DifferentWord"

Where # is a digit 0-9 and A is Letter (any letter) Some of the files have fewer or more words before the part with the numbers, and some of the words contain "-" and "(", ")" but are always seperated with "." and none of the file names contain spaces.

The files of the 3rd form should be left untouched.

I would rename all of these files of the first 2 forms to the form:
"### - .foo"

Where ### are the same 3 digits from up above in the same order.

I figured I'd have some:

for i in (ls *.foo | sort -nr)
do
test for conditions
store 3 digits to a, b, c
mv $i $a$b$c\ -\ .foo
done

and that I could filter out the 3rd case be ignoring files containing spaces, but I'm not really sure how to go about this or how to isolate the 3 important digits.

Any ideas on how to do these two things?



Sponsored Link
Ads by Google

Response Number 1
Name: jdieter
Date: November 30, 2005 at 22:10:21 Pacific
Reply:

Try this python script. It takes the first argument given to it (a filename in the format word.word.*#*##.word.word.foo) and renames the file to ### - .foo. If the file isn't in the format word.word.*#*##.word.word.foo, it won't be renamed.

Warning! This program doesn't check to make sure that no other files exist with the new name. If you use the same 3 digit sequence for two files, it will quietly write over the first one with the second one.

You'll want to call it from your bash script because it only handles one file at a time.

#!/usr/bin/env python

import sys
from string import find, replace
from os import rename

in_file = sys.argv[1]

fw_loc = find(in_file, ".")
sw_loc = find(in_file, ".", fw_loc + 1)
tw_loc = find(in_file, ".", sw_loc + 1)
frw_loc = find(in_file, ".", tw_loc + 1)
ffw_loc = find(in_file, ".", frw_loc + 1)

if ffw_loc != -1 and frw_loc != -1 and tw_loc != -1 and sw_loc != -1 and fw_loc != -1:
num = replace(in_file[sw_loc + 1:tw_loc], 'A', '')
num = replace(num, 'a', '')
ext = in_file[ffw_loc + 1:]

out_file = num + " - ." + ext

try:
rename(in_file, out_file)
except:
print "Unable to rename %s to %s" % (in_file, out_file)
sys.exit(1)
else:
print "%s doesn't match pattern *.*.*#*##.*.*.foo, so not renaming it" % in_file


0

Response Number 2
Name: jdieter
Date: November 30, 2005 at 22:13:30 Pacific
Reply:

This forum doesn't seem real good at keeping formatting. In python, the spacing is important, so everything between the if: and else: statements needs to be indented, as well as everything after the else: statement. Also the single line after try: needs to be indented twice, and the two lines after except: need to be indented twice.


0

Response Number 3
Name: FishMonger
Date: November 30, 2005 at 23:32:38 Pacific
Reply:

I agree, posting code in this forum is a real *@!^*! pain.

#!/usr/bin/perl -w

while (<*.foo>) {

$nbsp$nbsp$nbsp if ($_ =~ /^[a-z]+\.[a-z]+\.[a-z](\d)[a-z](\d\d)\.[a-z]+\.[a-z]+\.foo$/i ) {
$nbsp$nbsp$nbsp # matched "word.word.A#A##.word.word.foo"
$nbsp$nbsp$nbsp$nbsp$nbsp$nbsp rename($_, "$1$2 - .foo");
$nbsp$nbsp$nbsp }

$nbsp$nbsp$nbsp elsif ($_ =~ /^[a-z]+\.[a-z]+\.(\d{3})\.[a-z]+\.[a-z]+\.foo$/i ) {
$nbsp$nbsp$nbsp # matched "word.word.###.word.word.foo"
$nbsp$nbsp$nbsp$nbsp$nbsp$nbsp rename($_, "$1 - .foo");
$nbsp$nbsp$nbsp }
}


0

Response Number 4
Name: FishMonger
Date: November 30, 2005 at 23:34:16 Pacific
Reply:

Yep 1 little error and it's all screwed up.


0

Response Number 5
Name: FishMonger
Date: November 30, 2005 at 23:34:39 Pacific
Reply:

#!/usr/bin/perl -w

while (<*.foo>) {

if ($_ =~ /^[a-z]+\.[a-z]+\.[a-z](\d)[a-z](\d\d)\.[a-z]+\.[a-z]+\.foo$/i ) {
# matched "word.word.A#A##.word.word.foo"
rename($_, "$1$2 - .foo");
}

elsif ($_ =~ /^[a-z]+\.[a-z]+\.(\d{3})\.[a-z]+\.[a-z]+\.foo$/i ) {
# matched "word.word.###.word.word.foo"
rename($_, "$1 - .foo");
}
}


0

Related Posts

See More



Response Number 6
Name: bobpaul
Date: December 1, 2005 at 07:49:56 Pacific
Reply:

Thanks guys! I really appreciate it! Only problem is it looks like both of those scripts only work on a fixed number of words, but the number of words is actually variable.

I went on #bash on irc.freenode.net just now and they showed me how to do replacements in bash...

So here's what I have so far:
for i in *.foo
do
#filter out letter, periods, and hyphens
x=${i//[[:alpha:]]/}
x=${x//./}
x=${x//-/}
echo "$i renames to: $x - .foo"
done

problem that this has is that if the file name contains a space, such as "705 - foobar.foo" then i will get 3 different itterations, 705, -, and foobar.foo

I tried changing the for loop to:
for i in "$(ls *.foo)"
but that only gives me 1 $i containing ALL of the file names, each on 1 line.

So I guess that's problem 1 solved. Now I just have the space in file name issue.

I can do:
mkdir spaces
mv *\ * spaces/
[run the for loop]
mv spaces/* ./
rm -r spaces/

but that seems dirty and a little dangerous.


0

Response Number 7
Name: FishMonger
Date: December 1, 2005 at 10:42:12 Pacific
Reply:

As I understand it, you’re only concerned with the 3 numbers and not the unknown number of words before or after the numbers and skip any file that is already named correctly.

So we only need to look for file names with these patterns:

“### - .foo” -> these files get skipped

“.###.” Or “.A#A##” -> these files get renamed

I don’t do any shell scripting but here’s an updated version of my prior scipt.

#!/usr/bin/perl -w

while (<*.foo>) {
    next if /^\d\d\d - .foo$/;
    rename($_, "$1$2 - .foo") if ($_ =~ /\.[a-z]?(\d)(?:[a-z])?(\d\d)\./);
}


0

Response Number 8
Name: FishMonger
Date: December 1, 2005 at 10:44:17 Pacific
Reply:

One thing I forgot, the regex should be case insensitive.

/\.[a-z]?(\d)(?:[a-z])?(\d\d)\./i


0

Response Number 9
Name: bobpaul
Date: December 2, 2005 at 08:00:33 Pacific
Reply:

Oh, that looks great, Fish!

Now, after the files get renamed, I manually append an arbitrary number of words (space seperated) after the hyphen.

To ignore those, too would I just change it to this?
next if /^\d\d\d -(.*).foo$/;


0

Response Number 10
Name: FishMonger
Date: December 2, 2005 at 08:26:21 Pacific
Reply:

>> Now, after the files get renamed, I manually append an arbitrary number of words (space seperated) after the hyphen.

Why not do it in 1 step and append the words during the renaming?

>> To ignore those, too would I just change it to this?
next if /^\d\d\d -(.*).foo$/;

Yes, that should work. However, I forgot 1 minor detail; we should escape the . before foo.

/^\d\d\d -(.*)\.foo$/;


0

Sponsored Link
Ads by Google
Reply to Message Icon






Post Locked

This post is quite old and has been locked from receiving new replies. Please create a new posting instead.


Go to Linux Forum Home


Sponsored links

Ads by Google


Results for: Shell Script to rename files

Shell script to delete old files www.computing.net/answers/linux/shell-script-to-delete-old-files/30403.html

Shell script 2 accept file/dir name www.computing.net/answers/linux/shell-script-2-accept-filedir-name/22197.html

Shell script read from file www.computing.net/answers/linux/shell-script-read-from-file/17306.html