# rename file to substring last 7 characters



## cgjoker (Aug 13, 2003)

I know this should be basic unix but im having a heck of a time getting this to work for me for some reason.

I have a file called john1234567.dat

I want to rename it to 1234567

How do I do this?

here is what im trying ...

for FILE in `ls | grep john_*.dat`;
do 
$newname="`expr "$FILE" : ':$s/\([john_])([])'`" 
mv $FILE $newname
done


----------



## surfnschultz (Nov 17, 2003)

cp john1234567.dat 1234567

cat john1234567.dat > 1234567

These are easy, but might not meet your needs. Still looking for more help? let me know.


----------



## cgjoker (Aug 13, 2003)

I guess I should have elaborated a bit more.

The filename will never be the same. Each filename will have 7 digits on the end that id want to rename the file to.

thanks.


----------



## Squashman (Apr 4, 2003)

Will there always be an undscore between the name and number? Will the filename always start with *John_*? Makes it real easy if it does.


----------



## cgjoker (Aug 13, 2003)

no. the filename will always be different. i just need to get the last 7 characters of the filename, and rename that file to just those 7 characters.

that is kind of why i was trying to do a for loop in my attempt.


----------



## cgjoker (Aug 13, 2003)

in my example i know i have john_, but this was just to get it to work. really it should not even have the john_ in the substring.


----------



## Squashman (Apr 4, 2003)

Hmmm, not sure. So you want the 7 characters before the file extension and the file extension dropped. Let me clarify one more thing. Will those 7 characters be numbers or random characters.


----------



## Squashman (Apr 4, 2003)

I am assuming that the 7 digits will always be there and there will not be any characters in between them.


```
for FILE in `ls | grep .dat`;
do
newname=`echo $FILE | tr -d "[:alpha:]" | tr -d "."`
mv $FILE $newname
done
```
I am not sure if this will work for you or not. Basically what this script does is remove all alpha characters from the filename and the period. So hopefully those 7 digits are the only numerics in your filename.

hopefully that is the last time I edit this.


----------



## cgjoker (Aug 13, 2003)

I know its a really late reply, but there is a slight change to my requirement.

I actually need to keep the first 8 characters of a filename and drop the rest.

so ET345678file.dat would become ET345678

the first 8 characters would change constantly.

thanks.


----------



## cgjoker (Aug 13, 2003)

here is my latest attempt
for FILE in `ls *`;
do
newname=`echo $FILE | head -c9` 
mv $FILE $newname
done


----------



## Squashman (Apr 4, 2003)

cgjoker said:


> here is my latest attempt
> for FILE in `ls *`;
> do
> newname=`echo $FILE | head -c9`
> ...


Read the manual page for head and you will see why that wont work. But you were close. If you have your script in this directory it will rename your script as well. So I would suggest you move it into a different directory and chang the ls command to the directory you want listed.


```
for FILENAME in `ls *`;
do
newname=`echo $FILENAME | cut -b-8`
mv $FILENAME $newname
done
```


----------



## cgjoker (Aug 13, 2003)

thanks... I refined it a bit. 

for FILENAME in `ls *`;
do
newname=`echo $FILENAME | head -c8`
mv $FILENAME $newname
done

Im finding that your code is doing the same as mine. The problem im having is that both codes are only doing one file. The second or third file is deleted. 

So if I have 12345678_file.dat, 34567890_file2.dat....

I get only one file afterwards

12345678


----------



## cgjoker (Aug 13, 2003)

Nevermind,... both are working fine.

Thanks for your help


----------



## Squashman (Apr 4, 2003)

That is weird that the head command works for you. It is suppose to read the contents of a file and pull the first couple lines or bytes out of it.


----------



## cgjoker (Aug 13, 2003)

so... here is my dilemma now.

I have two files with the same first 8 characters so I want to add a number to each filename to make it unique. 

Here is what I came up with.

cd /data
for FILENAME in `ls *`;
do
name=`date +%b +%d`
for x in 1 2 3 4 5 6 7 8 9 
do 
#newname=`echo $FILENAME | head -c8`
newname=`echo $FILENAME | cut -b-8`
mv $FILENAME $newname$name$x
done
done


----------



## cgjoker (Aug 13, 2003)

Yeah, I know.. but it works. Try it out.

I don't know why my versioning isn't working though.


----------



## Squashman (Apr 4, 2003)

It's going to run thru that second for loop 9 times for every file. Why not just check for the existance of the file before you rename it. If the file exists then just add a number or date to the end of it.

If [ -e $FILENAME ]


----------



## Squashman (Apr 4, 2003)

Squashman said:


> It's going to run thru that second for loop 9 times for every file. Why not just check for the existance of the file before you rename it. If the file exists then just add a number or date to the end of it.
> 
> If [ -e $FILENAME ]


Oops, what I meant to say was

if [ -e $newname ] then (rename with date or extra number)
else (rename normally)


----------



## cgjoker (Aug 13, 2003)

Sure.. but how do I go about adding a sequential number to each instance of the same filename it finds? know what I mean?

so 

12345678_file1
12345678_file2

I want the result to be

123456781
123456782

eg.:

for file
do
if file
then
filename+1
fi 
done

something like this?


----------



## Squashman (Apr 4, 2003)

Rename the file with the current time? Right down to the second. Just a suggestion.

I see your point. If you have more than 2 files with the same name, this could turn into a big headache.

Or you create a While loop and dont exit it until you set the value to true. Then you can keep incrementing a value by one. 
This isn't the exact code, just what I think the flow of the script should be.

x=0
somevalue=false
while somevalue does not equal true
do
if [ -e newname ] then
x = x+1
newname=$newname$X
else somevalue=true

Do you see where I am going with this.


----------



## cgjoker (Aug 13, 2003)

sure do.. i was just trying out something very similar, ill let you know what I come up with.


----------



## Squashman (Apr 4, 2003)

I think you could just condense what I did above to
(Please dont shoot me if some of my syntax is off, i haven't tested any of this)

```
for FILENAME in `ls *`;
do
newname=`echo $FILENAME | cut -b-8`

x=0
While [ -e $newname ]
do
x=$x+1
newname=$newname$x
done

mv $filename $newname
done
```


----------



## cgjoker (Aug 13, 2003)

Thanks.. here is the syntax im using.

It seems to work partially. The increment of 1 isn't working. Im getting 0+1 added to the filename rather than 1, then 2, then 3.

for FILENAME in `ls *`;
do
newname=`echo $FILENAME | cut -b-8`
x=0
while [ -e $newname ];
do
x=$x+1
newname=$newname$x
done
mv $FILENAME $newname
done


----------



## Squashman (Apr 4, 2003)

I always miss a semicolon. That is why I got out of programming many years ago. Semicolons always drove me nuts.


----------



## cgjoker (Aug 13, 2003)

newest attempt.. but still not working. files are getting renamed to 
file
file1
file12

for FILENAME in `ls *`;
do
oldname=`echo $FILENAME | cut -b-8`
x=0
while [ -e $oldname ];
do
x=`expr $x + 1`
newname=$oldname$x
done
#echo $newname
#echo $oldname
mv -f $FILENAME $newname
done


----------



## cgjoker (Aug 13, 2003)

Okay... I got it working. I kind of simplified things but used the fundamentals.

x=0
for filename in `ls *`;
do
newname=`echo $filename | cut -b-8`
x=`expr $x + 1`
mv $filename $newname$x

done

thanks for your help.


----------



## cgjoker (Aug 13, 2003)

I forgot that I need to have each file with its own increments.. this just does all files regardless of first 8 characters. Back to the drawing board.


----------



## Squashman (Apr 4, 2003)

cgjoker said:


> I forgot that I need to have each file with its own increments.. this just does all files regardless of first 8 characters. Back to the drawing board.


Not sure what you mean by that. But here is what I think you need.


```
for FILENAME in `ls *`;
do
newname=`echo $FILENAME | cut -b-8`
oldname=$newname

x=0
While [ -e $newname ];
do
x=`expr $x + 1`
newname=$oldname$x
done

mv $FILENAME $newname
done
```


----------



## cgjoker (Aug 13, 2003)

thats the ticket... thanks again.


----------



## Squashman (Apr 4, 2003)

This is going to make your output look like this.

file
file1
file2

You could change it so that it looks like this
file1
file2
file3

You would need to change the default value of x to 1.

Then write an if statement to test whether the value of x is greater than 1. If it is, you can rename the original file that doesn't have the increment to $oldname1


----------



## cgjoker (Aug 13, 2003)

Sounds good. Thanks again for your help.


----------

