You are not logged in.

#1 2011-05-01 10:20:07

inknoir
Member
Registered: 2009-06-28
Posts: 29

[solved] recursive bulkrenaming

Hi, I have been using a renaming script from brisbin33, he was posting in "Handy self made command line utilities".

#!/bin/bash
#
# pbrisbin 2009
#
# take a retardedly named file or directory and rename it
# sanely
#
# adjust translate() as needed
#
###

message() { echo 'usage: renamer (--fake) <target> ...'; exit 1; }

# could always use more shit here...
translate() {
  tr -d '\n' | tr -d '\t' | tr -d \' | tr -d \" |\
    sed -r -e 's/.*/\L&/g' \
           -e 's/[ -]/_/g' \
           -e 's/_+/_/g'   \
           -e 's/^_|_$//g' \
           -e 's/ä/ae/g'   \
           -e 's/ö/oe/g'   \
           -e 's/ü/ue/g'   \
       -e 's/ß/ss/g'
}

rfile() {
  local dir old new

  dir="$(dirname "$1")"
  old="$(basename "$1")"
  new="$(echo $old | translate)"

  if [[ "$old" != "$new" ]]; then
    if $fake; then
      echo "$dir/$old --> $dir/$new"
    else
      mv -iv "$dir/$old" "$dir/$new"
    fi
  fi
}

rdir() {
  local dir

  while IFS='' read -d '' -r dir; do
    rfile "$dir"
  done < <(find "$1" -depth -print0)
}

[[ -z "$*" ]] && message

# allow a pretend run
if [[ "$1" = '--fake' ]]; then
  fake=true
  shift
else
  fake=false
fi

# do it to it
for arg in "$@"; do
  if [[ -d "$arg" ]]; then
    rdir "$arg"
  elif [[ -e "$arg" ]]; then
    rfile "$arg"
  else
    message
  fi
done

It saved me years of lifetime...but I still have one problem with it. When there is a name collision (a file with that name already exists and the script can't proceed therefore) the script just stops. I would prefer it, if the script could rename the file anyways, but append a number to get a unique filename (img.jpg => img02.jpg). Then I could do the cleanup later.
Sadly my scriptingskills are almost nonexistent. I am not even sure, if I have to implement that logic in the rfile-/rdir-functions or in the "do it" part of the script. As I have absolutely no clue, a little help would be much appreciated.

Thanks.

Last edited by inknoir (2011-05-08 17:48:05)

Offline

#2 2011-05-01 12:15:46

MrX
Member
From: Bavaria
Registered: 2010-07-10
Posts: 9

Re: [solved] recursive bulkrenaming

You could try it like this (not tested):

# In rfile()
# ...
 new="$(echo $old | translate)"
local i=1
while [[ -e "$new" ]]; do
  let i++
  # Note that this doesn't look very nice with filenames like "abc.tar.gz", as the number is inserted before the last "." (-> "abc.tar_2.gz")
  new="${new%.*}_$i.${new##*.}"
  # Alternatively, you can of course use the following (But this destroys the filename extension, e.g. "abc.jpg" becomes "abc.jpg_2"):
  new="${new}_$i"
done
# ...

Just choose one of the options and delete or comment the other line.

Offline

#3 2011-05-01 13:45:24

inknoir
Member
Registered: 2009-06-28
Posts: 29

Re: [solved] recursive bulkrenaming

Hm, I must admit that I'm not sure if I placed your snippet at the right place/commented out the right lines. But what I've tried so far, didn't work. Could you please post the whole function, MrX? Thank you very much.
Btw, "new="${new}_$i" seems to me the better choice, since it doesn't collide with any existing numbering (for example when a files name is Movie01.avi).

Offline

#4 2011-05-01 14:31:39

MrX
Member
From: Bavaria
Registered: 2010-07-10
Posts: 9

Re: [solved] recursive bulkrenaming

rfile() {
  local dir old new

  dir="$(dirname "$1")"
  old="$(basename "$1")"
  new="$(echo $old | translate)"
  local i=1
  while [[ -e "$new" ]]; do
    let i++
    new="${new}_$i"
  done
 
  if [[ "$old" != "$new" ]]; then
    if $fake; then
      echo "$dir/$old --> $dir/$new"
    else
      mv -iv "$dir/$old" "$dir/$new"
    fi
  fi
}

This seems to work.
Sorry, I should have posted the whole function before ;-)

// Edit: I only tested it with one file at first; Now i noticed my mistake

rfile() {                                                                                                                                                                                                            
  local dir old new                                                                                                                                                                                                  
                                                                                                                                                                                                                     
  dir="$(dirname "$1")"                                                                                                                                                                                              
  old="$(basename "$1")"                                                                                                                                                                                             
  new="$(echo $old | translate)"                                                                                                                                                                                     
                                                                                                                                                                                                                     
  if [[ "$old" != "$new" ]]; then                                                                                                                                                                                    
    if [[ -e "$new" ]]; then                                                                                                                                                                                         
      local i=1                                                                                                                                                                                                      
      while [[ -e "${new}_$i" ]]; do                                                                                                                                                                                 
        let i++                                                                                                                                                                                                      
      done                                                                                                                                                                                                           
      new="${new}_$i"                                                                                                                                                                                                
    fi                                                                                                                                                                                                               
    if $fake; then                                                                                                                                                                                                   
      echo "$dir/$old --> $dir/$new"                                                                                                                                                                                 
    else                                                                                                                                                                                                             
      mv -iv "$dir/$old" "$dir/$new"                                                                                                                                                                                 
    fi                                                                                                                                                                                                               
  fi                                                                                                                                                                                                                 
}

This time it should be correct ...
Sorry again.

Last edited by MrX (2011-05-01 14:47:44)

Offline

#5 2011-05-01 15:22:03

inknoir
Member
Registered: 2009-06-28
Posts: 29

Re: [solved] recursive bulkrenaming

No problem smile
Alas, it doesn't work with your snippet. If there is already a file with that name,it prompts me if I want to overwrite the file, then exits immediately (without waiting for any input).
I wonder if

'mv -iv "$dir/$old" "$dir/$new"' 

isn't wrong after your modification anyways. The -i option makes the moving interactive, which is not necessary, if there is no names colliding anymore. I changed the line to

'mv -v "$dir/$old" "$dir/$new"' 

Now it works again, but overwrites files, so it leaves your snippet unfunctional. hmm

Offline

#6 2011-05-01 18:29:06

inknoir
Member
Registered: 2009-06-28
Posts: 29

Re: [solved] recursive bulkrenaming

It works like a charm now!

Dankeschön smile



Edit:
I thought it worked, because it had no problems with my small testfolder (10 files). On my audiofolder (30.000 files) I get the following output and it stops:

[~/bin] rename2.sh /intern/audio/
mv: overwrite `/intern/audio/oldies/janis_joplin/janis_joplin_little_girl_blue.mp3'? [~/bin]

Edit2:
Nevermind, I am using vidir of the "moreutils" package, it works recursive and way faster than the script.

Last edited by inknoir (2011-05-08 17:50:38)

Offline

Board footer

Powered by FluxBB