Change all filenames in a directory

I have a directory of files and each file has a random 5 digit string at the beginning that needs to be removed. Plus, there are some files that will be identically named after the 5 digit string is removed and I want those eliminated or moved.
any ideas?

Ad hoc (untested):

#! /bin/bash

for OLD_FILE in $( ls $FOLDER | egrep '^[0-9]{5}' )
do
  NEW_FILE=$( echo ${OLD_FILE} | sed 's/^[0-9]{5}//' )
  if [ -f $FOLDER/$NEW_FILE ]
  then
    rm $FOLDER/$NEW_FILE
  fi
  mv $FOLDER/$OLD_FILE $FOLDER/$NEW_FILE
done

exit 0

Thanks for the response. I tried a test case with the code you gave and the filenames don't change.

#! /bin/bash

for OLD_FILE in $( ls | egrep '^[0-9]{5}' )
do
  NEW_FILE=$( echo ${OLD_FILE} | sed 's/^[0-9]{5}//' )
  if [ -f $NEW_FILE ]
  then
    echo $NEW_FILE'-duplicate'
  fi
  echo $OLD_FILE $NEW_FILE
done

exit 0

The code I think is not working is: ( echo ${OLD_FILE} | sed 's/^[0-9]{5}//' )
Any thoughts?

the 'echo' is doing what was coded. I suspect that dr.house didn't want to assume how you wanted to move/modify/etc the files, so they just echoed the output to show that the logic was sound. This leaves it up to you to move/modify/etc the code to do what you want.

I added the echo so if anything haywire happens then I don't mess stuff up. The echo shows the same filename, one after the other.
Is the 'sed' code correct? Am I doing something wrong?

Sure enough, sorry about that.

It may not be the most elegant, but:

NEW_FILE=$( echo ${OLD_FILE} | sed 's/^[0-9][0-9][0-9][0-9][0-9]//' )

Cool. That did it. Here is my pseudo-final solution: -also not pretty but does the job.

#! /bin/bash

for OLD_FILE in $( ls | egrep '^[[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]]' )
do
  NEW_FILE=$( echo ${OLD_FILE} | sed 's/^[[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]]//' )
  if [ -f $NEW_FILE ]
  then
    echo $NEW_FILE'-duplicate'
  fi
  echo $OLD_FILE $NEW_FILE

done

exit 0

Hi Crumb,

As far as i know /[A-Za-z0-9]/ works well in most cases instead of /[[:alnum:]]/ ,sou can try /[A-Za-z0-9]+/ instead of repeating alnum too. But below it is explained better. i got this part from a web page that was recommended by one of our moderators here, so check it:

For example, before the POSIX standard, you had to write /[A-Za-z0-9]/ to match
alphanumeric characters. If your character set had other alphabetic characters in it, this
would not match them, and if your character set collated differently from ASCII, this might not even match the ASCII alphanumeric characters. With the POSIX character classes, you can write /[[:alnum:]]/ to match the alphabetic and numeric characters in your character set.

I think you need [:digit:] instead of [:alnum:], no?

Here is an alternative way of doing it:

#!/bin/bash
for old_file in [0-9][0-9][0-9][0-9][0-9]*; do
  new_file=${old_file:5}
  if [ -f $new_file ]; then
    echo $new_file'-duplicate'
  fi
  echo $old_file $new_file
done

Try this one liner:

ls -1 [0-9][0-9][0-9][0-9][0-9]* | sed 's/\(^[0-9]\{5\}\)\(.*\)/mv & \2/' | ksh

Obviously, I missed something - correct would have been:

[house@leonov] echo 12345test.file | sed 's/^[0-9]\{5\}//'
test.file

I just tried it on my actual files and realized there are spaces involved. This seems to throw a wrench into what has been already used.
Any more ideas?

Depending on where those spaces are located (and assumed that eliminating them in advance is not an option), using double quotes may help you out:

[house@leonov] echo "12345te   st.file" | sed 's/^[0-9]\{5\}//'
te   st.file

I think the egrep is also separating everything at the space too.

---------- Post updated at 12:38 AM ---------- Previous update was at 12:35 AM ----------

I would also be ok removing all the spaces

My approach (- beware of recursion):

[house@leonov] more scrub.bash
#!/bin/bash

SCRIPT=$( readlink -f ${0} )
TARGET="$1"
if [ ! -d "$TARGET" ]
then
  echo "Usage: sh scrub.bash '[target folder]'"
  exit 1
else
  cd "$TARGET"
fi

BUFFER=/tmp/files.$$
ls -1 . > $BUFFER
while read FILE
do
  NAME=$( echo "$FILE" | sed -e "s/ /_/g" )
  if [ "$FILE" != "$NAME" ]
  then
    echo -ne "Scrubbed: "
    mv -vT "$FILE" "$NAME"
  fi
  if [ -d "$NAME" ]
  then
    sh $SCRIPT "$NAME"
  fi
done < $BUFFER
rm -f $BUFFER

exit 0

# [game over]
[house@leonov] ls testFiles
12345 test.file1  12345 test.file2  12345 test.file3
[house@leonov] sh scrub.bash testFiles
Scrubbed: `12345 test.file1' -> `12345_test.file1'
Scrubbed: `12345 test.file2' -> `12345_test.file2'
Scrubbed: `12345 test.file3' -> `12345_test.file3'
[house@leonov] ls testFiles
12345_test.file1  12345_test.file2  12345_test.file3

I thought you original requirement was to remove the numbers in begining from the file?
Hope this is what you are looking for:

ls -1 [0-9][0-9][0-9][0-9][0-9]* | sed 's/\(^[0-9]\{5\}\)\(.*\)/mv "&"  "\2"/' | ksh

This will over write any duplicate files that might be present after renaming.
You will finally end up having only one file.

That works perfect guy. I think that may be the winner. I had to install ksh but that works for me. I don't have to make changes to the spaces either.

Thanks

ps... the character string i need to remove at the beginning is actually two letters then a 4 digit number, then dash, then 2 digit number, then space, dash, space.
I realized I need to be more detailed in my description of the issue needing solving.

Glad it worked for you.
One bit of advice.
In unix files with space (or any improper char) is a pain in the neck.
As you go further it will cause more and more issues (including backup etc). Scrips will work fine when testing, but fail in realtime.
Resolve it at the root rather than through the script.