4 Replies Latest reply on Apr 28, 2015 7:38 AM by MadMax4025

    Renaming files in a book

    heatherb555 Newcomer

      Hi everyone,


      I need to rename files in a book, but from within the book. A Save as... won't update the cross refrences.


      I see an fcode for this (FCodes.KBD_BOOKRENAMEFILE), but I've been advised not to rely on these types of shortcuts.


      I don't see anything else documented in the Scripting Guide. Does anyone else have any other suggestions?


      Thanks so much!


      Heather A

        • 1. Re: Renaming files in a book
          MadMax4025 Newcomer

          Sadly I don't have an answer to this question and I'm hoping to bump this up to see if anybody out there now has an answer.


          I've been looking into it and I have found examples in ExtendScript suggesting (for illustrator):


          var myfile = File.openDialog( 'select your AI file…' );

          myfile.rename( 'NEW.ai' );


          However I want this to be done automatically without opening a dialog.

          I can programmatically cycle through book components and can skip over folders and groups. I'm hoping to rename files to a naming structure based upon the top level element name and it's attributes (all of which I have already done). Now all I need to do is to take the name that has been calculated and replace the old name with it (Similar to how you can simply click on a file in the book and rename it). Any thoughts or suggestions would be greatly appreciated.


          The following is what I have been trying so far:


          function SaveFM(Item) {

               var NewName,


               Filetype = Item.Name.split(".").pop();


               //NameEncoder returns a string containing the new file name (no path or file type);

               NewName = NameEncoder(Item, AbbrList) + "." + Filetype;


               //If the component being checked is a folder or a group the name returned is "Skip." Files such as TOC or Indexes will return starting with "XXX" to allow them to be skipped as well.

               if (NewName.substring(0, 4) !== "Skip" && NewName.substring(0, 3) !== "XXX") {

                    //I have tried the following, using .Save with the full file path, retProps, and saveProps (though these would probably create a new file which is not the end goal). All of them are throwing an error and I'm not sure what I am doing wrong.







          • 2. Re: Renaming files in a book
            frameexpert Champion

            Hi Heather,


            A book component has a Name property that you can use to rename the file. The name will show in the book window as a relative path from the book, but when setting the Name property, you use an absolute path.


            Of course this only changes the name in the book window. To rename the file on disk you can use ExtendScript's File object methods. Then, you will have to open all of the other components in the book and resolve any cross-references that used to point to the renamed document. Basically, you are doing what the built-in command does, but via scripting. If you need help with the individual steps, please let me know.



            • 3. Re: Renaming files in a book
              MadMax4025 Newcomer

              Hi Rick,


              Thanks for the info. I've gotten some code that creates an array of all the files in my book, their old names, and their new names.


              However, the "Name" quality of the files are grayed out and for some reason don't change. I can easily change the "Label" and the "PrintFileName" (both of their icon's are blue). Is there some other way I should be doing this?


              I've attached the section of my code that is doing the renaming:


                  for (var i = 0, len = FileArray.length; i < len; i++) {

                      ThisFile = FileArray[i][0];

                      OldName = FileArray[i][1];

                      NewName = FileArray[i][2];

                      ThisFile.Name = NewName;

                      ThisFile.Label = NewName.split(".").shift(); //since the label does not contain a file type

                      ThisFile.PrintFileName = NewName.split(".").shift() + ".ps" //since file type is .ps


              • 4. Re: Renaming files in a book
                MadMax4025 Newcomer

                Just following up for anybody else who might need this in the future.


                My hangup was that pulling files from the book itself created Doc objects, not File objects (beginners mistake, you hate to see it). Anyway, here are some of the functions that I came up with to handle this task for anybody who needs it. Please be warned, this is quite literally my first ExtendScript project so this may not be the most efficient way to have done this (I'm always open to constructive criticism from those more experienced than myself). I know I went overkill with notes in the code, that was requested by colleagues who know less about code than I do so that if I were no longer employed for some reason another person could come in and understand exactly what the code was doing.



                function fileNameReplacer(FullArray, CodeBook, BookFile) {
                    /*The fileNameReplacer steps through all of the files in the book looking for those who need to be renamed.
                        The function first renames all of the files, and then cycles through each file's Crossreferences and updates the
                        names to reflect name changes*/
                    /*Local variables are created*/
                    var FileName,
                    FileArray = FullArray;
                    /*Loops through all of the files in the book*/
                    for (var i = 0, len = FileArray.length; i < len; i++) {
                        /*Tests if the file is type 255 which would signify it is a folder or a group (These will not be renamed and would throw errors)*/
                        if (FileArray[i][0].type == 255) {
                            /*If the file is identified as a group or folder, it is removed from the Array with the "splice" command*/
                            FileArray.splice(i, 1);
                            /*The counters for this loop are then adjusted to reflect the new length of the "FileArray" variable*/
                            i = i - 1;
                            len = len - 1;
                            /*Starts the next round of the loop (which is actually repeating the same loop but without the group or folder in the Array)*/
                        /*If the file being looked at is not a folder or group, it is assigned to the "ThisFile" variable*/
                        ThisFile = FileArray[i][0];
                        /*Checks the file to see if it's element catalog has values. If there are no values, it would mean that there is no data from which
                            to develop the encoded name, and likely means the file is something like a cover page or table of contents which do not need encoding*/
                        if (ThisFile.ElementCatalog.length !== 0) {
                            /*If the element catalog has items in it, the name of the current file being examined is assigned to the "FullName" variable*/
                            FullName = ThisFile.Name;
                            /*The FullName is then split into an array at each backslash (Backslashes in JavaScrip have their own meaning, in order to
                                input a single backslash two must be used). The last item of the array is the file name which is assigned to the "FileName"
                                variable using the "pop" command*/
                            FileName = FullName.split("\\").pop();
                            /*The FileName is then split at the period, and the file extension with a leading period is assigned to the "FileType" variable.*/
                            FileType = "." + FileName.split(".").pop();
                            /*The file path without file name is assigned to the "FilePath" variable. This is done by identifying where in the "FullName" variable
                                the "FileName" begins, and then taking a substring of the "FullName" up to that point.*/
                            FilePath = FullName.substr (0, (FullName.indexOf(FileName)));
                            /*The new encoded file name is found by running the current file through the nameEncoder function along with the Abbreviation List
                                (Called "CodeBook" in this function). The value produced by the nameEncoder function is assigned to the "EncodedName" variable*/
                            EncodedName = nameEncoder(ThisFile, CodeBook);
                            /*The encoded name and original name are then assigned to locations 2 and 1 in the File array respetively*/
                            FileArray[i][2] = FilePath + EncodedName + FileType;
                            FileArray[i][1] = FullName;
                            /*The old name and new name are compared to see if a change has actually occurred*/
                            if (FileArray[i][1] === FileArray[i][2]) {
                                /*If no change has occured, the file is removed from the array using the "splice" command, since it will only slow down later processes.*/
                                FileArray.splice(i, 1);
                                /*The loop counters are updated to reflect the change in FileArray length*/
                                i = i - 1;
                                len = len - 1;
                                /*Starts the next round of the loop (which is actually repeating the same loop but with the file not requiring renaming removed)*/               
                        } else {
                            /*If the element catalog for the current file does not have any values it is removed from the "FileArray" using the "splice" command*/
                            FileArray.splice(i, 1);
                            /*The loop counters are updated to reflect the change in FileArray length*/
                            i = i - 1;
                            len = len - 1;
                            /*Starts the next round of the loop (which is actually repeating the same loop but with the file lacking elements removed)*/
                    /*At this point the FileArray contains only files that can, and have been renamed; along with their current and new names*/
                    /*Loops through all files in the FileArray*/
                    for (var l = 0, lenA = FileArray.length; l < lenA; l++) {
                        /*Assigns the current file, its old name, and its new name to the "ThisFile", "OldName", and "NewName" variables respectively*/
                        ThisFile = FileArray[l][0];
                        OldName = FileArray[l][1];
                        NewName = FileArray[l][2];
                        /*Opens the current file assigned to "ThisFile" as a File object. File objects allow for changes on the drive itself to be made, while
                            changing the .Name attribute of a Doc object will not. This allows for the encoded names to be applied directly to the files themseves.*/
                        OpenFile = File(ThisFile.Name);
                        /*Changes the file's label to the value of "NewName" and removes the file type (as the label does not show file type)*/
                        ThisFile.Label = NewName.split(".").shift();
                        /*Changes the PrintFileName value to the value of "NewName" with the file type changed to ".ps"*/
                        ThisFile.PrintFileName = NewName.split(".").shift() + ".ps";
                    /*Traverses all files in the books and renames the target the book is looking for. If this is not done, the book will still think the old names exist and will
                        try to find them to no avail. "traverse" function sends each component in the book through another function,
                          in this case the bookComponentRenamer, and supplies the second function with a parameter, FileArray here.*/
                    traverse(BookFile, bookComponentRenamer, FileArray);
                    xrefRenamer(FullArray, FileArray);
                    /*Saves the book file with the updated component names*/
                    /*When the book is closed, the BookFile variable will no longer function. Assigning the current books name to the "BookName" varibales will allow the book to be reopened*/
                    BookName = BookFile.Name;
                    /*All open files are closed*/
                    /*Curent book is reopened*/
                    BookFile = openBook (BookName);
                    /*All book files (now with updated names) are opened*/
                    traverse(BookFile, openfile);
                    /*Returns the updated book back to the location that originally called the fileNameReplacer function*/
                    return BookFile;
                function bookComponentRenamer(Component, FileArray) {
                    /*The bookComponentRenamer compares the current book component with names on the FileArray (these are files that have name changes.
                        If a match is found, that compent's name is changed within the book itself. This ensures that the names the book file is looking for reflect the updated file names created by this program*/
                    for (var i = 0, len = FileArray.length; i < len; i++) {
                        if (Component.Name === FileArray[i][1]) {
                            Component.Name = FileArray[i][2];
                function xrefRenamer(AllFiles, RenamedFiles) {
                    var ThisFile,
                    for (var i = 0, len = AllFiles.length; i < len; i++) {
                        /*Assigns the first cross reference in the current file to the "ThisXREF" variable*/
                        ThisFile = AllFiles[i][0];
                        ThisXREF = ThisFile.FirstXRefInDoc;
                        /*Whether "ThisXREF" contains a valid cross reference (having a null value means the file has no cross references, or we have already
                            looped through them all and can proceed to the next file in the FileArray)*/
                        while (ThisXREF.XRefFile !== null) {
                            /*Assigns the next cross reference in the file to the "NextXREF" variable*/
                            NextXREF = ThisXREF.NextXRefInDoc;
                            /*Loops through all of the files in the FileArray. This will let the current cross reference be compared to the files being renamed and see if
                                there are any matches*/
                            for (var j = 0, lenA = RenamedFiles.length; j < lenA; j++) {
                                    /*Assigns the old name and the new name of the file being compared to cross references to the "OldName" and "NewName" variables respectively*/
                                    OldName = RenamedFiles[j][1];
                                    NewName = RenamedFiles[j][2];
                                    XREFTest = ThisXREF.XRefFile.indexOf(OldName);
                                    /*Tests if the current cross reference being examined links to the current comparison file*/
                                    if (0 <= XREFTest) {
                                        /*If yes, the cross reference is updated with the new name*/
                                        ThisXREF.XRefFile = ThisXREF.XRefFile.replace(OldName, NewName);
                                        /*Ends the comparison loop for this cross reference as the correct replacement has been found*/
                            /*Assigns "ThisXREF" with the value of the "NextXREF" the comparison loop starts again*/
                            ThisXREF = NextXREF;