Skip to main content
Known Participant
May 30, 2026
Answered

Divide multiple paths into divided vector layers?

  • May 30, 2026
  • 2 replies
  • 63 views

I accidentally merged all the shapes into a single vector layer in Photoshop. Luckily, they still retained their individual paths, so I could use the path selection tool to select them. However, my job requires me to separate them into individual vector layers, and there are thousands of such shapes, like this:

 

    Correct answer c.pfaffenbichler
    // split layer with vector mask into layers according to subpathitems;
    // 2026, use it at yout own risk;
    if (app.documents.length > 0) {
    if (hasVectorMask() == true) {
    var myDocument = activeDocument;
    var theLayer = myDocument.activeLayer;
    var thePath = collectPathInfoFromDesc2023 (myDocument, myDocument.pathItems[myDocument.pathItems.length-1]);
    for (var m = 0; m < thePath.length; m++) {
    var thisLayer = theLayer.duplicate();
    myDocument.activeLayer = thisLayer;
    changeSelectedPath2020([thePath[m]])
    myDocument.activeLayer = theLayer;
    };
    theLayer.remove()
    }
    };
    ////// collect path info from actiondescriptor, indices start at 1, not 0 //////
    function collectPathInfoFromDesc2023 (myDocument, thePath) {
    var originalRulerUnits = app.preferences.rulerUnits;
    app.preferences.rulerUnits = Units.POINTS;
    // based of functions from xbytor’s stdlib;
    var idPath = charIDToTypeID( "Path" );
    var ref = new ActionReference();
    // check if thePath is an index or a dom-path;
    if (thePath.constructor == Number) {
    ref.putIndex(idPath, thePath)
    }
    else {
    thePath.select();
    var ref = new ActionReference();
    ref.putEnumerated( charIDToTypeID( "Path" ), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
    };
    // get stuff;
    var desc = app.executeActionGet(ref);
    var pname = desc.getString(cTID('PthN'));
    // create new array;
    var theArray = new Array;
    var pathComponents = desc.getObjectValue(cTID("PthC")).getList(sTID('pathComponents'));
    // for subpathitems;
    for (var m = 0; m < pathComponents.count; m++) {
    var listKey = pathComponents.getObjectValue(m).getList(sTID("subpathListKey"));
    var operation1 = pathComponents.getObjectValue(m).getEnumerationValue(sTID("shapeOperation"));
    switch (operation1) {
    case 1097098272:
    var operation = 1097098272 //cTID('Add ');
    break;
    case 1398961266:
    var operation = 1398961266 //cTID('Sbtr');
    break;
    case 1231975538:
    var operation = 1231975538 //cTID('Intr');
    break;
    default:
    // case 1102:
    var operation = sTID('xor') //ShapeOperation.SHAPEXOR;
    break;
    };
    // for subpathitem’s count;
    for (var n = 0; n < listKey.count; n++) {
    theArray.push(new Array);
    var points = listKey.getObjectValue(n).getList(sTID('points'));
    try {var closed = listKey.getObjectValue(n).getBoolean(sTID("closedSubpath"))}
    catch (e) {var closed = false};
    // for subpathitem’s segment’s number of points;
    for (var o = 0; o < points.count; o++) {
    var anchorObj = points.getObjectValue(o).getObjectValue(sTID("anchor"));
    var anchor = [anchorObj.getUnitDoubleValue(sTID('horizontal')), anchorObj.getUnitDoubleValue(sTID('vertical'))];
    var thisPoint = [anchor];
    try {
    var left = points.getObjectValue(o).getObjectValue(cTID("Fwd "));
    var leftDirection = [left.getUnitDoubleValue(sTID('horizontal')), left.getUnitDoubleValue(sTID('vertical'))];
    thisPoint.push(leftDirection)
    }
    catch (e) {
    thisPoint.push(anchor)
    };
    try {
    var right = points.getObjectValue(o).getObjectValue(cTID("Bwd "));
    var rightDirection = [right.getUnitDoubleValue(sTID('horizontal')), right.getUnitDoubleValue(sTID('vertical'))];
    thisPoint.push(rightDirection)
    }
    catch (e) {
    thisPoint.push(anchor)
    };
    try {
    var smoothOr = points.getObjectValue(o).getBoolean(cTID("Smoo"));
    thisPoint.push(smoothOr)
    }
    catch (e) {thisPoint.push(false)};
    theArray[theArray.length - 1].push(thisPoint);
    };
    theArray[theArray.length - 1].push(closed);
    theArray[theArray.length - 1].push(operation);
    };
    };
    // by xbytor, thanks to him;
    function cTID (s) { return cTID[s] || cTID[s] = app.charIDToTypeID(s); };
    function sTID (s) { return sTID[s] || sTID[s] = app.stringIDToTypeID(s); };
    // reset;
    app.preferences.rulerUnits = originalRulerUnits;
    return theArray;
    };
    ////// change a path based on collectPathInfoFromDesc2023-array //////
    function changeSelectedPath2020(theArray) {
    var originalRulerUnits = app.preferences.rulerUnits;
    app.preferences.rulerUnits = Units.PIXELS;
    // thanks to xbytor;
    cTID = function(s) { return app.charIDToTypeID(s); };
    sTID = function(s) { return app.stringIDToTypeID(s); };
    var desc1 = new ActionDescriptor();
    var ref1 = new ActionReference();
    ref1.putEnumerated( cTID('Path'), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
    desc1.putReference(sTID('null'), ref1);
    var list1 = new ActionList();
    for (var m = 0; m < theArray.length; m++) {
    var thisSubPath = theArray[m];
    var desc2 = new ActionDescriptor();
    desc2.putEnumerated(sTID('shapeOperation'), sTID('shapeOperation'), thisSubPath[thisSubPath.length - 1]);
    var list2 = new ActionList();
    var desc3 = new ActionDescriptor();
    desc3.putBoolean(cTID('Clsp'), thisSubPath[thisSubPath.length - 2]);
    var list3 = new ActionList();
    for (var n = 0; n < thisSubPath.length - 2; n++) {
    var thisPoint = thisSubPath[n];
    var desc4 = new ActionDescriptor();
    var desc5 = new ActionDescriptor();
    desc5.putUnitDouble(cTID('Hrzn'), cTID('#Rlt'), thisPoint[0][0]);
    desc5.putUnitDouble(cTID('Vrtc'), cTID('#Rlt'), thisPoint[0][1]);
    desc4.putObject(cTID('Anch'), cTID('Pnt '), desc5);
    var desc6 = new ActionDescriptor();
    desc6.putUnitDouble(cTID('Hrzn'), cTID('#Rlt'), thisPoint[1][0]);
    desc6.putUnitDouble(cTID('Vrtc'), cTID('#Rlt'), thisPoint[1][1]);
    desc4.putObject(cTID('Fwd '), cTID('Pnt '), desc6);
    var desc7 = new ActionDescriptor();
    desc7.putUnitDouble(cTID('Hrzn'), cTID('#Rlt'), thisPoint[2][0]);
    desc7.putUnitDouble(cTID('Vrtc'), cTID('#Rlt'), thisPoint[2][1]);
    desc4.putObject(cTID('Bwd '), cTID('Pnt '), desc7);
    desc4.putBoolean(cTID('Smoo'), thisPoint[3]);
    list3.putObject(cTID('Pthp'), desc4);
    };
    desc3.putList(cTID('Pts '), list3);
    list2.putObject(cTID('Sbpl'), desc3);
    desc2.putList(cTID('SbpL'), list2);
    list1.putObject(cTID('PaCm'), desc2);
    };
    desc1.putList(cTID('T '), list1);
    executeAction(cTID('setd'), desc1, DialogModes.NO);
    /// get index;
    var ref = new ActionReference();
    ref.putProperty(stringIDToTypeID("property"), stringIDToTypeID("itemIndex"));
    ref.putEnumerated( charIDToTypeID("Path"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
    var pathDesc = executeActionGet(ref);
    var myPathItem = activeDocument.pathItems[pathDesc.getInteger(stringIDToTypeID("itemIndex")) - 1];
    app.preferences.rulerUnits = originalRulerUnits;
    return myPathItem
    };
    ////// from »Flatten All Masks.jsx« by jeffrey tranberry //////
    function hasVectorMask() {
    var hasVectorMask = false;
    try {
    var ref = new ActionReference();
    var keyVectorMaskEnabled = app.stringIDToTypeID( 'vectorMask' );
    var keyKind = app.charIDToTypeID( 'Knd ' );
    ref.putEnumerated( app.charIDToTypeID( 'Path' ), app.charIDToTypeID( 'Ordn' ), keyVectorMaskEnabled );
    var desc = executeActionGet( ref );
    if ( desc.hasKey( keyKind ) ) {
    var kindValue = desc.getEnumerationValue( keyKind );
    if (kindValue == keyVectorMaskEnabled) {
    hasVectorMask = true;
    }
    }
    }catch(e) {
    hasVectorMask = false;
    }
    return hasVectorMask;
    };

     

     

    2 replies

    c.pfaffenbichler
    Community Expert
    c.pfaffenbichlerCommunity ExpertCorrect answer
    Community Expert
    May 30, 2026
    // split layer with vector mask into layers according to subpathitems;
    // 2026, use it at yout own risk;
    if (app.documents.length > 0) {
    if (hasVectorMask() == true) {
    var myDocument = activeDocument;
    var theLayer = myDocument.activeLayer;
    var thePath = collectPathInfoFromDesc2023 (myDocument, myDocument.pathItems[myDocument.pathItems.length-1]);
    for (var m = 0; m < thePath.length; m++) {
    var thisLayer = theLayer.duplicate();
    myDocument.activeLayer = thisLayer;
    changeSelectedPath2020([thePath[m]])
    myDocument.activeLayer = theLayer;
    };
    theLayer.remove()
    }
    };
    ////// collect path info from actiondescriptor, indices start at 1, not 0 //////
    function collectPathInfoFromDesc2023 (myDocument, thePath) {
    var originalRulerUnits = app.preferences.rulerUnits;
    app.preferences.rulerUnits = Units.POINTS;
    // based of functions from xbytor’s stdlib;
    var idPath = charIDToTypeID( "Path" );
    var ref = new ActionReference();
    // check if thePath is an index or a dom-path;
    if (thePath.constructor == Number) {
    ref.putIndex(idPath, thePath)
    }
    else {
    thePath.select();
    var ref = new ActionReference();
    ref.putEnumerated( charIDToTypeID( "Path" ), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
    };
    // get stuff;
    var desc = app.executeActionGet(ref);
    var pname = desc.getString(cTID('PthN'));
    // create new array;
    var theArray = new Array;
    var pathComponents = desc.getObjectValue(cTID("PthC")).getList(sTID('pathComponents'));
    // for subpathitems;
    for (var m = 0; m < pathComponents.count; m++) {
    var listKey = pathComponents.getObjectValue(m).getList(sTID("subpathListKey"));
    var operation1 = pathComponents.getObjectValue(m).getEnumerationValue(sTID("shapeOperation"));
    switch (operation1) {
    case 1097098272:
    var operation = 1097098272 //cTID('Add ');
    break;
    case 1398961266:
    var operation = 1398961266 //cTID('Sbtr');
    break;
    case 1231975538:
    var operation = 1231975538 //cTID('Intr');
    break;
    default:
    // case 1102:
    var operation = sTID('xor') //ShapeOperation.SHAPEXOR;
    break;
    };
    // for subpathitem’s count;
    for (var n = 0; n < listKey.count; n++) {
    theArray.push(new Array);
    var points = listKey.getObjectValue(n).getList(sTID('points'));
    try {var closed = listKey.getObjectValue(n).getBoolean(sTID("closedSubpath"))}
    catch (e) {var closed = false};
    // for subpathitem’s segment’s number of points;
    for (var o = 0; o < points.count; o++) {
    var anchorObj = points.getObjectValue(o).getObjectValue(sTID("anchor"));
    var anchor = [anchorObj.getUnitDoubleValue(sTID('horizontal')), anchorObj.getUnitDoubleValue(sTID('vertical'))];
    var thisPoint = [anchor];
    try {
    var left = points.getObjectValue(o).getObjectValue(cTID("Fwd "));
    var leftDirection = [left.getUnitDoubleValue(sTID('horizontal')), left.getUnitDoubleValue(sTID('vertical'))];
    thisPoint.push(leftDirection)
    }
    catch (e) {
    thisPoint.push(anchor)
    };
    try {
    var right = points.getObjectValue(o).getObjectValue(cTID("Bwd "));
    var rightDirection = [right.getUnitDoubleValue(sTID('horizontal')), right.getUnitDoubleValue(sTID('vertical'))];
    thisPoint.push(rightDirection)
    }
    catch (e) {
    thisPoint.push(anchor)
    };
    try {
    var smoothOr = points.getObjectValue(o).getBoolean(cTID("Smoo"));
    thisPoint.push(smoothOr)
    }
    catch (e) {thisPoint.push(false)};
    theArray[theArray.length - 1].push(thisPoint);
    };
    theArray[theArray.length - 1].push(closed);
    theArray[theArray.length - 1].push(operation);
    };
    };
    // by xbytor, thanks to him;
    function cTID (s) { return cTID[s] || cTID[s] = app.charIDToTypeID(s); };
    function sTID (s) { return sTID[s] || sTID[s] = app.stringIDToTypeID(s); };
    // reset;
    app.preferences.rulerUnits = originalRulerUnits;
    return theArray;
    };
    ////// change a path based on collectPathInfoFromDesc2023-array //////
    function changeSelectedPath2020(theArray) {
    var originalRulerUnits = app.preferences.rulerUnits;
    app.preferences.rulerUnits = Units.PIXELS;
    // thanks to xbytor;
    cTID = function(s) { return app.charIDToTypeID(s); };
    sTID = function(s) { return app.stringIDToTypeID(s); };
    var desc1 = new ActionDescriptor();
    var ref1 = new ActionReference();
    ref1.putEnumerated( cTID('Path'), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
    desc1.putReference(sTID('null'), ref1);
    var list1 = new ActionList();
    for (var m = 0; m < theArray.length; m++) {
    var thisSubPath = theArray[m];
    var desc2 = new ActionDescriptor();
    desc2.putEnumerated(sTID('shapeOperation'), sTID('shapeOperation'), thisSubPath[thisSubPath.length - 1]);
    var list2 = new ActionList();
    var desc3 = new ActionDescriptor();
    desc3.putBoolean(cTID('Clsp'), thisSubPath[thisSubPath.length - 2]);
    var list3 = new ActionList();
    for (var n = 0; n < thisSubPath.length - 2; n++) {
    var thisPoint = thisSubPath[n];
    var desc4 = new ActionDescriptor();
    var desc5 = new ActionDescriptor();
    desc5.putUnitDouble(cTID('Hrzn'), cTID('#Rlt'), thisPoint[0][0]);
    desc5.putUnitDouble(cTID('Vrtc'), cTID('#Rlt'), thisPoint[0][1]);
    desc4.putObject(cTID('Anch'), cTID('Pnt '), desc5);
    var desc6 = new ActionDescriptor();
    desc6.putUnitDouble(cTID('Hrzn'), cTID('#Rlt'), thisPoint[1][0]);
    desc6.putUnitDouble(cTID('Vrtc'), cTID('#Rlt'), thisPoint[1][1]);
    desc4.putObject(cTID('Fwd '), cTID('Pnt '), desc6);
    var desc7 = new ActionDescriptor();
    desc7.putUnitDouble(cTID('Hrzn'), cTID('#Rlt'), thisPoint[2][0]);
    desc7.putUnitDouble(cTID('Vrtc'), cTID('#Rlt'), thisPoint[2][1]);
    desc4.putObject(cTID('Bwd '), cTID('Pnt '), desc7);
    desc4.putBoolean(cTID('Smoo'), thisPoint[3]);
    list3.putObject(cTID('Pthp'), desc4);
    };
    desc3.putList(cTID('Pts '), list3);
    list2.putObject(cTID('Sbpl'), desc3);
    desc2.putList(cTID('SbpL'), list2);
    list1.putObject(cTID('PaCm'), desc2);
    };
    desc1.putList(cTID('T '), list1);
    executeAction(cTID('setd'), desc1, DialogModes.NO);
    /// get index;
    var ref = new ActionReference();
    ref.putProperty(stringIDToTypeID("property"), stringIDToTypeID("itemIndex"));
    ref.putEnumerated( charIDToTypeID("Path"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
    var pathDesc = executeActionGet(ref);
    var myPathItem = activeDocument.pathItems[pathDesc.getInteger(stringIDToTypeID("itemIndex")) - 1];
    app.preferences.rulerUnits = originalRulerUnits;
    return myPathItem
    };
    ////// from »Flatten All Masks.jsx« by jeffrey tranberry //////
    function hasVectorMask() {
    var hasVectorMask = false;
    try {
    var ref = new ActionReference();
    var keyVectorMaskEnabled = app.stringIDToTypeID( 'vectorMask' );
    var keyKind = app.charIDToTypeID( 'Knd ' );
    ref.putEnumerated( app.charIDToTypeID( 'Path' ), app.charIDToTypeID( 'Ordn' ), keyVectorMaskEnabled );
    var desc = executeActionGet( ref );
    if ( desc.hasKey( keyKind ) ) {
    var kindValue = desc.getEnumerationValue( keyKind );
    if (kindValue == keyVectorMaskEnabled) {
    hasVectorMask = true;
    }
    }
    }catch(e) {
    hasVectorMask = false;
    }
    return hasVectorMask;
    };

     

     

    jane-e
    Community Expert
    Community Expert
    May 30, 2026

    @c.pfaffenbichler 

    Did you write this code just now?

    Jane

    c.pfaffenbichler
    Community Expert
    Community Expert
    May 30, 2026

    I had the functions that do the "heavy lifting" available from previous projects, so it was not that difficult. And I am sure one could streamline the script further.

    c.pfaffenbichler
    Community Expert
    Community Expert
    May 30, 2026

    If you need to maintain Vector Masks (as opposed to rasterising the Shape Layers) I see no other option than a custom Script. 

    But it is certainly possible.