Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 6 Oct 2003 23:23:26 -0600
From:      steve <groups@xscd.com>
To:        questions@freebsd.org
Subject:   Shell script--batch rename files
Message-ID:  <200310062323.26081.groups@xscd.com>

next in thread | raw e-mail | index | archive | help
Hello All--

I'm a novice shell programmer, but I thought I would begin to learn
by writing a script that had a need for but could not find an 
equivalent of on the Internet. I decided to post it here (a) in case
anyone else might find it useful and (b) to expose it to more 
experienced script authors who might be kind enough to offer
helpful criticisms or suggestions.

(the script appears in its entirety at the end of this email)

I wrote the script (it works with /bin/sh or BASH) to address the following
problem-- I have many folders of image files (from my digital camera,
received as email attachments or downloaded from the Internet) that I have
sorted into folders by theme (such as "friends," "family," "vacation_2003,"
etc.), and many of them have filenames I would like to change on a
per-directory basis, either because they are too generic 
(IMG_0105.JPG, IMG_0106.JPG, etc.), or because the filenames have spaces or
unusual characters within them, or simply to make all the filenames
in each directory have the same root name with a unique numerical index
appended, maintaining their original filename extension (or adding
one, if desired).

The script works on files in the shell's current directory only 
(and not on any subdirectories within), and renames every file 
(but not subdirectories or symbolic links) using a user-specified 
name followed by a numerical index, followed by the file's original
filename extension (if there was any).

On my machine I have titled the script mvb (like a "batch" version
of mv), and it seems to work well so far during the couple months
I have been working on it. Like I said, I post it here in case 
anyone else may find it useful and to learn from any criticisms,
comments and suggestions it might generate.

Thank you,
Steve


-------CUT-HERE----shell-script-begins-on-next-line-------
#!/bin/sh
#----------------------------------------------------
# Change the path above to point to the location on
# your computer of either the Bourne shell (sh) or
# the BASH (Bourne Again) shell (bash).
#
# This shell script was written to "batch rename" files
# (change the name of many files at once) in the
# current working directory.
# 
# For his personal use the author named this script
# mvb (MV-Batch) in reference to the mv command
# of *nix/Linux (which this script uses).
#
# Written by: Steve Doonan, Portales, NM US
# Email: xscd@xscd.com
# Date: October, 2003
#----------------------------------------------------

if [ $# -eq 0 ]
   then
      cat << _EOF_

--------------------------------------------------
You did not specify a NEWNAME for the files.

After the name of the command please enter
a SPACE followed by the name you would like
all the files in the current directory to be
renamed to.
--------------------------------------------------

_EOF_
      exit
fi

NEWNAME="$(echo "$1" | tr -Cs '[:alnum:]' '_')"

cat << _EOF_

-------------------------------------------------------
Rename files to--> $NEWNAME
Current directory--> $(pwd)

   Continue? (Press RETURN or ENTER)
   TO QUIT, type q (then press RETURN or ENTER)
   FOR INFORMATION, type i (then press RETURN or ENTER)
-------------------------------------------------------

_EOF_

read CONTINUE
case $CONTINUE
in
    [!i]* ) exit ;;
       i  ) cat << _EOF_

----------------------------------------------------------------
INFORMATION

This shell script (Bourne or BASH) will RENAME all visible files
(files that don't begin with a dot) in the current directory, to
a name you specify, appending a numerical index to each filename
so that each is unique, and retaining the original filename
extension, if one exists.

This script will NOT rename subdirectories or symbolic links
contained within the current directory, nor will it descend into
subdirectories to rename files within them.

If the script does not see what looks like an existing valid
FILENAME EXTENSION (3-4 characters following a dot at the end
of a filename), it will ask for one. If you WANT to add a
filename extension, just type 3 or 4 characters (i.e. jpg, txt,
html), with or without a preceding dot--the script will provide
the dot if you do not. If you do NOT want the filename to have
an extension, just press RETURN or ENTER at that prompt without
typing any characters, and no filename extension will be added.

To QUIT this program at any time, press CONTROL-C
To CONTINUE, press RETURN or ENTER
----------------------------------------------------------------

_EOF_
    read CONTINUE ;;
esac

INDEX=0

make_zero-padded_index_number ()
{
INDEX=$(($INDEX + 1))
INDEX_COUNT="$(echo "$INDEX" | wc -c)"
PADDING_ZEROS="$(ls "$(pwd)" | wc -l | tr '[:digit:]' '0' | tr -d '[:space:]')"
INDEX_ALPHANUMERIC="$(echo "${PADDING_ZEROS}${INDEX}" | cut -c$INDEX_COUNT-)"
}

for I in *
   do
      #-----------------------------------------
      # if file is NOT a directory or a link...
      #-----------------------------------------
      if [ -f "$I" -a ! -L "$I" ]
         then
         #-----------------------------------------------
         # if filename has a 3 or 4 character extension...
         #-----------------------------------------------
         if echo "$I" | grep "\.[^.0-9]\{3,4\}$" > /dev/null
            then
            #------------------------------------------------
            # assign filename extension to variable EXTENSION
            #------------------------------------------------
            EXTENSION="$(echo "$I" | sed 's/^.*\(\.[^.]*\)$/\1/')"
         #-----------------------------------------------------
         # otherwise, ask for a filename extension (or none)...
         #-----------------------------------------------------
         else
            echo ""
            echo '------------------------------------------------------------'
            echo "FILENAME: $I"
            echo "No (or improbable) filename extension found"
            echo "Enter new filename extension, or press RETURN or ENTER"
            echo -n "for no filename extension: "
            read NEW_EXTENSION
            #-----------------------------------------------------------------
            # cut the new extension (if any) down to no more than 4 characters
            #-----------------------------------------------------------------
            NEW_EXTENSION="$(echo "$NEW_EXTENSION" | sed 's/^\.*\(.\{0,4\}\).*$/\1/'| tr -C '[:alnum:]\12' '_' )"
            echo '------------------------------------------------------------'
            echo ""
            if [ -n "$NEW_EXTENSION" ]
               then
               EXTENSION=".${NEW_EXTENSION}"
            else
               EXTENSION=''
            fi
         fi
         #----------------------------------------------------------------------
         # at this point, EXTENSION should be set correctly--an alphanumeric
         # index number is created (by the function make_zero-padded_index_number)
         # and the file is renamed (with a slightly different name if the computed
         # filename already exists in the current directory).
         #----------------------------------------------------------------------
         make_zero-padded_index_number
         RENAME_TO="${NEWNAME}${INDEX_ALPHANUMERIC}${EXTENSION}"
         if [ -e "$RENAME_TO" ]
            then
               RENAME_TO="${NEWNAME}${INDEX_ALPHANUMERIC}a${EXTENSION}"
         fi
         chmod 664 "$I"
         mv -iv -- "$I" "$RENAME_TO"
      fi
   done
cat << _EOF_

---------------------------------------------------
  The files have been renamed. Script exiting...
---------------------------------------------------

_EOF_



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200310062323.26081.groups>