Skip navigation
Home/Support/

Forums

7385 Views 20 Replies Latest reply: Oct 11, 2011 12:21 PM by Joe Seven RSS
User 8 posts since
Feb 14, 2005
Currently Being Moderated

Feb 12, 2008 5:33 PM

PS3 script to batch rename layers

Sometimes, I make copies of layers (for example: copy little diamonds to align into a shape of the letter M). Each time I "alt+drag" the content in that layer (to make a copy of it), PS makes a copy and then appends the name of the layer to something like "diamond copy 3". After making a ton of copies (and because I'm anal about having actual names for each layer), I want each layer to read "diamond". Instead of manually renaming all these layers, is there a way to highlight the affected layers and choose to rename all layers according to what you want?
  • MarkWalsh User 465 posts since
    Feb 28, 2008
    Currently Being Moderated
    1. Feb 28, 2008 9:14 AM (in response to (Shandy_Elliott))
    Re: PS3 script to batch rename layers
    You're in luck. I just finished writing this yesterday. :)

    This will remove " copy", " copy 1"... etc from all open files. Let me know how it works out for you.

    ////////////////////////////////////////////////////////////////////// /////////
    // Script Name: RenameLayers.jsx
    // Version: 1.0
    // Date: 2/27/08
    // Usage: Removes 'copy 1, copy 2, etc' from name of all layers
    ////////////////////////////////////////////////////////////////////// /////////

    #target photoshop
    //$.localize = true;
    var displayDialogMode = app.displayDialogs;

    app.bringToFront();
    app.bringToFront();
    app.displayDialogs = DialogModes.NO;

    processObjects(app.documents, processDocument,function () {alert("You have no documents open")})
    app.displayDialogs = displayDialogMode;

    ////////////////////////////////////////////////////////////////////// /////////
    // Function: processObjects
    // Usage: Runs theMainFunction on every object in list theObjects
    // Input: List of objects (documents, layers, etc.), Function to run on each object, Function to run on parent if there are no object
    // Return: value returned from function used
    ////////////////////////////////////////////////////////////////////// /////////
    function processObjects(theObjects, theMainFunction, theAlternateFunction) {
    var returnValue = null;
    if (theObjects.length ==0) {
    if (!(theAlternateFunction == undefined) && !(theAlternateFunction == null) && !(theAlternateFunction == "")) {
    returnValue = theAlternateFunction (theObjects.parent);
    }
    } else {
    if (!(theMainFunction == undefined) && !(theMainFunction == null) && !(theMainFunction == "")) {
    for (var i = theObjects.length -1; i> -1; i--) {
    returnValue += theMainFunction (theObjects[i], i);
    }
    }
    }
    return returnValue;
    }

    ////////////////////////////////////////////////////////////////////// /////////
    // Function: processDocument
    // Usage: Processes layers of document with 'processLayer' function
    // Input: Document object, Document object index
    // Return: none
    ////////////////////////////////////////////////////////////////////// /////////
    function processDocument(objectRef, i) {
    app.activeDocument = objectRef
    processObjects(objectRef.layers, processLayer, null);
    }

    ////////////////////////////////////////////////////////////////////// /////////
    // Function: processLayer
    // Usage: Removes 'copy' from layer name (processes Layer Set contents)
    // Input: Layer object, Layer Object index
    // Return: none
    ////////////////////////////////////////////////////////////////////// /////////
    function processLayer(objectRef, i) {
    if (objectRef.typename == 'LayerSet') {
    var layerCount = processObjects(objectRef.layers, processLayer);
    }
    renameLayer(objectRef)
    return 0
    }

    ////////////////////////////////////////////////////////////////////// /////////
    // Function: renameLayer
    // Usage: Removes 'copy' from layer name (processes Layer Set contents)
    // Input: Layer object, Layer Object index
    // Return: none
    ////////////////////////////////////////////////////////////////////// /////////
    function renameLayer(objectRef) {
    var theRegEx = new RegExp(/^(.*)(copy(\s(\d)+)*)+$/)
    if (theRegEx.test(objectRef.name)) {
    var indexNumber = 0

    indexnumber = objectRef.name.indexOf(" copy")
    objectRef.name = objectRef.name.substr(0,indexnumber)
    }
    return 0
    }
  • MarkWalsh User 465 posts since
    Feb 28, 2008
    Currently Being Moderated
    3. Feb 29, 2008 6:39 AM (in response to (Shandy_Elliott))
    Re: PS3 script to batch rename layers
    Paste into a text program (notepad on PC, TextEdit on mac) and save into the 'Scripts' directory in the 'Presets' directory of your Photoshop application folder with a '.js' or '.jsx' extension (e.g. "RenameLayers.jsx").

    To activate, select "Scripts" from the"File" menu and select the saved script.
  • GagnonEric User 101 posts since
    Jun 18, 2007
    Currently Being Moderated
    5. Mar 12, 2008 2:38 PM (in response to (Shandy_Elliott))
    Re: PS3 script to batch rename layers
    Hi!

    I will surely have a look at the script... Does it handle well hierarchical nested layers?

    In my current project, i have some documents that are very heavy (by exemple more than 1000 layers!).

    The automated renaming of around 300 layers in particular document is a process that take as much as 7 hours! (Applescript on a 1.8 G5 computer/4go ram).

    It's not fully clear to me if it's the logic of the script/the scripting api speed or the heavy use of PSD document that is at fault..

    If only i had more time for pluggin developpement! :)

    Eric
  • MarkWalsh User 465 posts since
    Feb 28, 2008
    Currently Being Moderated
    6. Mar 12, 2008 3:11 PM (in response to (Shandy_Elliott))
    Re: PS3 script to batch rename layers
    Yes, it will handle all layers in every layer set. (in every opened file)

    If you have a lot of layers, it could take a while as it opens each layer set and scrolls through every layer. On the files I've used it on, it runs pretty speedy. I think it will also run much faster than an applescript.
  • GagnonEric User 101 posts since
    Jun 18, 2007
    Currently Being Moderated
    7. Mar 12, 2008 3:33 PM (in response to (Shandy_Elliott))
    Re: PS3 script to batch rename layers
    I have tested it.. it works like advertised (including layers in groups).

    The script is fast on small sample but get quite slow on heavy documents ... so maybe my problem is more related to document size and maybe not worth investigating other scripting alternatives (but i'm pretty sure that on the same set your script would be faster).

    The only bug i have found is that the script dont keep track of the visibility of layers. If a layer is invisible (when you do the renaming), the layer should be invisible when you are done with the processing.

    That "problem" is also visible in a normal user interaction through the interface (select a layer make the layer visible). It's questionable in the user interface and a real problem with automation even if you record and set back the property. It must be clear to the users that if a script is crashing that document need to be reloaded!
  • MarkWalsh User 465 posts since
    Feb 28, 2008
    Currently Being Moderated
    8. Mar 13, 2008 5:48 AM (in response to (Shandy_Elliott))
    Re: PS3 script to batch rename layers
    It looks like changing the name of the layer makes it visible (unless it is the selected layer). I'll see if I can find the time to edit the script to activate each layer before it renames it. This should solve that problem. I'd also like it to restore the state of the layer sets that it opens to select each layer, and if I have it select each layer before renaming, then it should also end with the originally selected layer selected.
  • GagnonEric User 101 posts since
    Jun 18, 2007
    Currently Being Moderated
    9. Mar 13, 2008 8:23 AM (in response to (Shandy_Elliott))
    Re: PS3 script to batch rename layers
    I must say that in my scripts, i had quite a few problems to get around while working with layers! (and not all where solved!)
  • MarkWalsh User 465 posts since
    Feb 28, 2008
    Currently Being Moderated
    10. Mar 13, 2008 8:23 AM (in response to (Shandy_Elliott))
    Re: PS3 script to batch rename layers
    I made a quick rewrite to the renameLayer function. This should fix the problem with invisible layers. I ran the script on a large document just now, and it did take a while (although MUCH faster than would be manually, plus more accurate). It switches to the layer to rename it, and switches back to the original selected layer afterwards. I will rewrite it later to switch to the layer before renaming (hopefully that should solve that slowdown).

    function renameLayer(objectRef) {
    var theRegEx = new RegExp(/(\s*copy\s*\d*)+$/)

    if (theRegEx.test(objectRef.name)) {
    // save state of layer (visible or invisible)
    var layerVisible = objectRef.visible
    var indexNumber = 0
    indexnumber = objectRef.name.indexOf(" copy")
    objectRef.name = objectRef.name.substr(0,indexnumber)
    objectRef.visible = layerVisible
    }
    return 0
    }
  • matt-dd User 4 posts since
    Jan 31, 2010
    Currently Being Moderated
    11. May 12, 2010 6:30 PM (in response to MarkWalsh)
    Re: PS3 script to batch rename layers

    Hi Mark,


    thanks for this, worked a treat and saved me a whole lot of 'fun' in removing copy from each layer.

  • Mothator User 3 posts since
    Jul 13, 2010
    Currently Being Moderated
    12. Jul 13, 2010 12:59 PM (in response to matt-dd)
    Re: PS3 script to batch rename layers

    Hello Mark,

     

    Also thanks for sharing the script, very usefull. I'm trying to add something to the script so that only selected layers in the document where layers are selected are processed with your renameLayer function. But i can't seem to find the correct code to only get the selected layers and layers sets

    from this document. Is this even possible to do ? I'm not an experienced coder myself but I can read your script (and write fairly basic scripts). I was trying to fill an array with the selected layer and layer-sets that needed to be renamed, but I even got stuck there.

     

    Thanks,

    Fred

  • Michael L Hale Contributor 1,450 posts since
    Feb 22, 2005
    Currently Being Moderated
    13. Jul 13, 2010 1:19 PM (in response to Mothator)
    Re: PS3 script to batch rename layers

    Mothator,

     

    What version of Photoshop are you using. I have a script that removes 'copy' from selected layers but it needs a document descriptor key that is CS4 or higher.

  • Mothator User 3 posts since
    Jul 13, 2010
    Currently Being Moderated
    14. Jul 13, 2010 2:03 PM (in response to Michael L Hale)
    Re: PS3 script to batch rename layers

    I'm using CS4 ...

  • Michael L Hale Contributor 1,450 posts since
    Feb 22, 2005
    Currently Being Moderated
    15. Jul 13, 2010 2:35 PM (in response to Mothator)
    Re: PS3 script to batch rename layers

    Try this. Just select the layers you want 'copy' removed from and run this script.

    if( app.documents.length > 0 ){
    app.activeDocument.suspendHistory('Rename selected layers','removeCopyFromSelectedLayersNames()');
    }
    function removeCopyFromLayerName(){
         if( getSelectedLayersIdx().length > 1 ){
              var selectedLayers = getSelectedLayersIdx();
              makeActiveByIndex( selectedLayers[0], false );
         }
       var startLoop = Number( !hasBackground() );
       var endLoop = getNumberOfLayer() + 1; 
       for( var l = startLoop;l < endLoop; l++){
            while( !isValidActiveLayer( l ) ) {
                l++;
            }
              var oldName =  getLayerNameByIndex( l );
              var newName = oldName.replace(/\scopy\s?\d*$/i,'');
              putLayerNameByIndex( l, newName )
         }
         if( selectedLayers != undefined ) makeActiveByIndex( selectedLayers, false );
    }
    function removeCopyFromSelectedLayersNames(){
         var selectedLayers = getSelectedLayersIdx();
         for( var l = 0;l < selectedLayers.length; l++){
              var oldName =  getLayerNameByIndex( selectedLayers[ l ] );
              var newName = oldName.replace(/\scopy.*$/i,'');
              makeActiveByIndex( selectedLayers[ l ], false );
              putLayerNameByIndex( selectedLayers[ l ], newName )
         }
         makeActiveByIndex( selectedLayers, false );
    }
    function getNumberOfLayer(){ 
    var ref = new ActionReference(); 
    ref.putEnumerated( charIDToTypeID('Dcmn'), charIDToTypeID('Ordn'), charIDToTypeID('Trgt') ); 
    var desc = executeActionGet(ref); 
    var numberOfLayer = desc.getInteger(charIDToTypeID('NmbL')); 
    return numberOfLayer; 
    }
    function getLayerNameByIndex( idx ) { 
        var ref = new ActionReference(); 
        ref.putProperty( charIDToTypeID('Prpr') , charIDToTypeID( 'Nm  ' )); 
        ref.putIndex( charIDToTypeID( 'Lyr ' ), idx );
        return executeActionGet(ref).getString(charIDToTypeID( 'Nm  ' ));; 
    }
    function putLayerNameByIndex( idx, name ) {
         if( idx == 0 ) return;
        var desc = new ActionDescriptor();
            var ref = new ActionReference();
            ref.putIndex( charIDToTypeID( 'Lyr ' ), idx );
        desc.putReference( charIDToTypeID('null'), ref );
            var nameDesc = new ActionDescriptor();
            nameDesc.putString( charIDToTypeID('Nm  '), name );
        desc.putObject( charIDToTypeID('T   '), charIDToTypeID('Lyr '), nameDesc );
        executeAction( charIDToTypeID('setd'), desc, DialogModes.NO );
    }
    function getActiveLayerIndex() {
         var ref = new ActionReference();
         ref.putProperty( 1349677170 , 1232366921 );
         ref.putEnumerated( 1283027488, 1332896878, 1416783732 );
         var res = executeActionGet(ref).getInteger( 1232366921 )
                                                           - Number( hasBackground() );
         return res;   
    }
    function isValidActiveLayer( idx ) {
         var propName = stringIDToTypeID( 'layerSection' );
         var ref = new ActionReference(); 
         ref.putProperty( 1349677170 , propName);
         ref.putIndex( 1283027488, idx );
         var desc =  executeActionGet( ref );
         var type = desc.getEnumerationValue( propName );
         var res = typeIDToStringID( type ); 
         return res == 'layerSectionEnd' ? false:true;
    }
    function hasBackground(){
        var res = undefined;
        try{
            var ref = new ActionReference();
            ref.putProperty( 1349677170 , 1315774496); 
            ref.putIndex( 1283027488, 0 );
            executeActionGet(ref).getString(1315774496 );; 
            res = true;
        }catch(e){ res = false}
        return res;
    }
    function getSelectedLayersIdx(){
         var selectedLayers = new Array;
         var ref = new ActionReference();
         ref.putEnumerated( charIDToTypeID('Dcmn'), charIDToTypeID('Ordn'), charIDToTypeID('Trgt') );
         var desc = executeActionGet(ref);
         if( desc.hasKey( stringIDToTypeID( 'targetLayers' ) ) ){
              desc = desc.getList( stringIDToTypeID( 'targetLayers' ));
              var c = desc.count 
              var selectedLayers = new Array();
              for(var i=0;i<c;i++){
                   selectedLayers.push(  desc.getReference( i ).getIndex());
              }
         }else{
              var ref = new ActionReference(); 
              ref.putProperty( charIDToTypeID('Prpr') , charIDToTypeID( 'ItmI' )); 
              ref.putEnumerated( charIDToTypeID('Lyr '), charIDToTypeID('Ordn'), charIDToTypeID('Trgt') );
              selectedLayers.push( executeActionGet(ref).getInteger(charIDToTypeID( 'ItmI' )));
         }
         return selectedLayers;
    }
    function makeActiveByIndex( idx, visible ){
         if( idx.constructor != Array ) idx = [ idx ];
         for( var i = 0; i < idx.length; i++ ){
              var desc = new ActionDescriptor();
              var ref = new ActionReference();
              ref.putIndex(charIDToTypeID( 'Lyr ' ), idx[i])
              desc.putReference( charIDToTypeID( 'null' ), ref );
              if( i > 0 ) {
                   var idselectionModifier = stringIDToTypeID( 'selectionModifier' );
                   var idselectionModifierType = stringIDToTypeID( 'selectionModifierType' );
                   var idaddToSelection = stringIDToTypeID( 'addToSelection' );
                   desc.putEnumerated( idselectionModifier, idselectionModifierType, idaddToSelection );
              }
              desc.putBoolean( charIDToTypeID( 'MkVs' ), visible );
              executeAction( charIDToTypeID( 'slct' ), desc, DialogModes.NO );
         }     
    }
    
  • Mothator User 3 posts since
    Jul 13, 2010
    Currently Being Moderated
    16. Jul 13, 2010 3:50 PM (in response to Michael L Hale)
    Re: PS3 script to batch rename layers

    Hi Michael,

     

    It seems to be working perfectly, thanks for sharing this !!

     

    Greetings,

    f,

  • matt-dd User 4 posts since
    Jan 31, 2010
    Currently Being Moderated
    17. Jul 14, 2010 10:04 PM (in response to Michael L Hale)
    Re: PS3 script to batch rename layers

    Hi,

     

    I copy'n'pasted your script into Text Edit and saved as .jsx, saved that into PS4 > Presets > Scripts and tried it but it didn't work.

     

    I selected the layer I wanted to remove 'copy' from but got the following error.

     

    Picture 2.png

    Any possible solutions? The initial script at the top of this thread worked, but I have too many layers to work through to use it effectively.

     

    Any help appreciated.

     

    --cheers, matt

  • Michael L Hale Contributor 1,450 posts since
    Feb 22, 2005
    Currently Being Moderated
    18. Jul 14, 2010 10:42 PM (in response to matt-dd)
    Re: PS3 script to batch rename layers

    I am not sure why it is not woking for you unless Text Edit did not save it as plain text.

     

    That script is one of two that I have in a Configurator panel I made. One button removes 'copy' from all layers and the other button removes from selected layers. You can get the panel at http://ps-scripts.com/bb/viewtopic.php?f=10&t=3056

  • matt-dd User 4 posts since
    Jan 31, 2010
    Currently Being Moderated
    19. Jul 14, 2010 11:20 PM (in response to Michael L Hale)
    Re: PS3 script to batch rename layers

    Thanks Michael, that did the trick!

     

    -matt

  • Joe Seven User 6 posts since
    Sep 28, 2011
    Currently Being Moderated
    20. Oct 11, 2011 12:21 PM (in response to (Shandy_Elliott))
    Re: PS3 script to batch rename layers

    This is very handy, thanks for creating it.

     

    Suggestion: It would be very helpful to be able to rename all your selected files in one shot, ie change 25 layers all named "shape 2" to "button".

     

    Cheers,

     

    J

More Like This

  • Retrieving data ...

Bookmarked By (0)