LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Directory Traverse & Rename Script (https://www.linuxquestions.org/questions/programming-9/directory-traverse-and-rename-script-673990/)

fsckin 10-03-2008 12:00 PM

Directory Traverse & Rename Script
 
I am running this script in cygwin, but since I found the original here, I figured it would be OK to post here.

I'm using this to extract the contents of a version control system folder dump into something usable. It was previously gziped up (eg 1.1.gz) but that's been fixed.

The way my modified script works now, it runs through all subdirectories and properly renames files with names like "1.1" and changes them to be foldername.ext, which is perfect. It also has the bonus of overwriting a 1.1 file with a 1.2 file (which happens to be a newer version) which is also the behavior I want.

What isn't perfect is when it does something I don't want, like this:
mv PATH\fileone.ext PATH.ext

fileone.ext will NEVER start with "1" and I'd like to stop the script from performing any commands on a file that begins with "1"

Here's the directory structure
Code:

C:\PATH

C:\PATH\fileone.ext
C:\PATH\filetwo.ext
C:\PATH\filethree.ext

C:\PATH\folder1,d\
-----------------\1.1
-----------------\1.2

C:\PATH\folder2,d\
-----------------\1.1
-----------------\1.2
-----------------\1.3

C:\PATH\folder3,d\
-----------------\1.1
-----------------\1.2
-----------------\1.3

C:\PATH\folder4,d\subdirectory1\
------------------------------\filefour.ext
------------------------------\filefive.ext
------------------------------\filesix.ext

C:\PATH\folder5,d\subdirectory2,d\
------------------------------\1.1
------------------------------\1.2
------------------------------\1.3




Code:

#!/bin/bash
while read file
do
  basename=${file##*/}
  if [ $(expr index "$basename" .) -gt 0 ]
  then
    extension=.${file##*.}
  else
    extension=""
  fi
  dirname=${file%/*}
  newname=${dirname##*/}
  newname=`echo "$newname$extension" | cut -d',' -f1`
  echo mv "$file" "$dirname/$newname"
done < <(find FOLDERPATH -type f)




-Wayne

zmanea 10-04-2008 03:42 PM

First you say that you want it to process files that start with a 1

Quote:

it runs through all subdirectories and properly renames files with names like "1.1" and changes them to be foldername.ext, which is perfect. It also has the bonus of overwriting a 1.1 file with a 1.2 file (which happens to be a newer version) which is also the behavior I want.
Then you say that you dont?

Quote:

fileone.ext will NEVER start with "1" and I'd like to stop the script from performing any commands on a file that begins with "1"
It is hard to give an exact example without understanding what you are trying to do. There are a couple of ways to filter out files with what you are doing, you can start by changing your find command. Something like the following:

find -type f -name "[!1]*"

jschiwal 10-04-2008 05:21 PM

Cygwin will access the C:\ drive like "/cygdrive/c/". It would help if you posted a segment from the results of a find command so we can see what it looks like exactly. Then describe the "after" better with an example.

Also, it appears that FOLDERPATH is supposed to be replaced with the base directory to start the search. You are taking it literally.

I would suggest adding a line in the top like "FOLDERPATH=/cygdrive/c/projects" and then changing the last line to "done < <(find "$FOLDERPATH" -type f)". This will use a variable in the last line which is defined before the loop starts.

Code:

echo mv "$file" "$dirname/$newname"
This is a good idea. Inserting an echo allows you to debug the script before doing anything destructive. You might want to redirect the output to a file if there is a large number of files.

Is the index command a bash function, which you haven't posted? There is a C library function index() which returns a pointer to the first instance of a character in a string.

You might consider writing your own function that checks for a (.[[:digit:]]+)+ pattern at the end of a string. Look at the "=~" conditional operator.

fsckin 10-05-2008 01:43 AM

Quote:

Originally Posted by zmanea (Post 3300338)
find -type f -name "[!1]*"

That's pretty damn smart.

I did get it functional, but ran into the ugly beast of spaces in the filename. So I echoed all commands into a file, which I piped into bash. Worked well. I ended up doing this in two parts, and the old version of my script was overwritten... anywho 80,000 files later it ran into problems with "too long of filename", but that was with files that were in nested folders 30 deep.



Here's what it eventually ended up like, I'm pretty damn sure this is NOT optimal with the grep and cut commands, but it did the job.

Code:

#!/bin/bash
while read file
do
  basename=${file##*/}
  if [ $(expr index "$basename" .) -gt 0 ]
  then
    extension=.${file##*.}
  else
    extension=""
  fi
  dirname=${file%/*}
  newname=${dirname##*/}
  newname=`echo "$newname$extension" | cut -d',' -f1`
if echo "$dirname" | grep -q ,d""
then
  newlocation=`echo "$dirname" | cut -d',' -f1`
  echo "mv \"$dirname/$newname\" \"$newlocation\""
  echo "rm -r \"$dirname\""
fi
done < <(find FOLDER -type f)

Here's an example of how I should have done it:

Code:

mv "Base/Sub/Test File Name.ext,d/1.1" "Base/Sub/Test File Name.ext"
rm -r "Base/Sub/Test File Name.ext,d/"

I might figure out something more elegant, but this should be a one time process. I wont ever need to go back to the old way things were compressed and in weird folder names, etc.


All times are GMT -5. The time now is 01:30 AM.