Copy link to clipboard
Copied
Hello,
Does anyone know why my illustrator is crashing when I run this script? When I take out the loop for the pathItems, it does what I want. It selects the group named "5". Now I need to select all the paths with a specfic name like "50", but illustrator keep crashing.
var doc = app.activeDocument;
var activeLayer = doc.activeLayer;
var getLayer = doc.layers.getByName("clouds");
for (var i = 0; i < doc.layers.length; i++) {
layer = doc.layers[i];
if (layer.name === "clouds") {
//doc.activeLayer = doc.layers.getByName("clouds");
for (var ii = 0; ii < doc.groupItems.length; ii++) {
group = doc.groupItems[ii];
if (group.name === "5") {
//group.selected = true;
for (var p = 0; p< doc.pathItems.length; p++) {
path = doc.pathItems[p];
if (path.name === "50") {
path.selected = true;
alert("path loop success");
} // end path if statement
} // end path loop
} // end group if statement
} // end group loop
} // end layer if statement
} // end layer loop
Copy link to clipboard
Copied
you are looping over yourself with the for loops. your layer loop has you looping through each item in that layer for every layer so you are revisiting the same items. without seeing the specific file, I'd expect this is why its "crashing" as its processing a lot.
If you're looking for just paths with a specific name you can remove all of the loops except the path items loop and then have the if path name == statement.
Copy link to clipboard
Copied
I'm not sure what you're trying to do but the way the script is layed out it seems you want to find a path named "50" that is inside a group named "5" that is inside a layer named "clouds"
if that's the case, then there's no need to query all groups and paths in other layers
if that's not your goal, then you need to elaborate and share more details
check if this edited script works
var doc = app.activeDocument;
var activeLayer = doc.activeLayer;
//var getLayer = doc.layers.getByName("clouds");
for (var i = 0; i < doc.layers.length; i++) {
layer = doc.layers[i];
if (layer.name === "clouds") {
//doc.activeLayer = doc.layers.getByName("clouds");
for (var ii = 0; ii < layer.groupItems.length; ii++) { // ****edited
group = layer.groupItems[ii]; // ****edited
if (group.name === "5") {
//group.selected = true;
for (var p = 0; p < group.pathItems.length; p++) { // ****edited
path = group.pathItems[p]; // ****edited
if (path.name === "50") {
path.selected = true;
alert("path loop success");
} // end path if statement
} // end path loop
} // end group if statement
} // end group loop
} // end layer if statement
} // end layer loop
Copy link to clipboard
Copied
Hi @amberw42080715 some things are faster and slower via the scripting API. One operation that is incredibly slow is setting a page item as "selected". The fastest way for multiple items is to set the selection to an array of page items—in one operation—as I show in the script below..
Also traversing a complex document looking through item names can be inefficient without some care. I have spent a lot of time crafting the `getItems` function (over several years!) and now I can pretty much throw anything at it and it can deliver the goods.
My example script doesn't check for GroupItem names, but if you read the getItems documentation you will see that it can handle it too, or you can add a predicate into the `selectByName` function to check the item's parent. Or you can do two calls to `getItems`, one for a group named X and another searching inside that group (pass it the parameter {from: myGroup}. Let me know if you'd like guidance on this.
- Mark
/**
* @file Select Paths By Name.js
*
* Example using `getItems` function to select items by name.
*
* There are two main efficiencies:
* 1. The `getItems` function collects items in a careful way
* rarely getting caught up in memory issues.
* 2. The selection is made in one operation.
*
* @author m1b
* @version 2025-11-09
* @discussion https://community.adobe.com/t5/illustrator-discussions/illustrator-crashes-when-running-a-script-to-loop-through-paths/m-p/15580281
*/
(function () {
if (0 === app.documents.length)
return alert('Please open a document and try again.');
var doc = app.activeDocument;
var matchMe = prompt('Enter name to search for:', 'Untitled');
if (!matchMe)
return;
/** Returns true when the item name matches the target. */
function selectByName(item) {
return item.name && item.name === matchMe;
}
var itemsToSelect = getItems({ from: doc, filter: selectByName })
// select the items
doc.selection = itemsToSelect;
})();
/** ------------------------------------------------------------------- *
* GET ITEMS *
* -------------------------------------------------------------------- *
* @author m1b *
* @version 2024-03-01 *
* -------------------------------------------------------------------- *
* Collects page items from a `from` source, eg. a Document, Layer, *
* GroupItem, or Array. Will look inside group items up to `maxDepth`. *
* Search can be filtered using `filter` function. Note that the *
* filter function is evaluated last in the filtering process. *
* -------------------------------------------------------------------- *
* Example 1. Get all items in document: *
* *
* var myItems = getItems({ from: app.activeDocument }); *
* *
* -------------------------------------------------------------------- *
* Example 2. Get all selected items except groups: *
* *
* var myItems = getItems({ *
* from: app.activeDocument.selection, *
* getGroupItems: false, *
* }); *
* *
* -------------------------------------------------------------------- *
* Example 3. Using `filter` function to choose item type: *
* *
* var myItems = getItems({ *
* from: app.activeDocument, *
* filter: function (item) { *
* return ( *
* 'PathItem' === item.typename *
* || 'CompoundPathItem' === item.typename *
* ); *
* } *
* }); *
* *
* -------------------------------------------------------------------- *
* Example 4. Using `filter` function: *
* *
* var myItems = getItems({ *
* from: app.activeDocument, *
* filter: onlyPngLinks *
* }); *
* *
* function onlyPngLinks(item, depth) { *
* return ( *
* 'PlacedItem' === item.typename *
* && '.png' === item.file.name.slice(-4).toLowerCase() *
* ); *
* }; *
* *
* -------------------------------------------------------------------- *
* Example 4. Using the `filter` function for custom collecting: *
* *
* This example bypasses the normal returned array and instead *
* captures items in an "external" array `itemsByDepth`. *
* *
* var itemsByDepth = []; *
* *
* function getItemsByDepth(item, depth) { *
* if (undefined == itemsByDepth[depth]) *
* itemsByDepth[depth] = []; *
* itemsByDepth[depth].push(item); *
* }; *
* *
* getItems({ *
* from: app.activeDocument, *
* filter: getItemsByDepth *
* }); *
* *
* -------------------------------------------------------------------- *
* @param {Object} options - parameters
* @param {PageItem|Array<PageItem>|Document|Layer} options.from - the thing(s) to look in, eg. a selection.
* @param {Function} [options.filter] - function that, given a found item, must return true (default: no filtering).
* @param {Boolean} [options.getPageItems] - whether to include page items in returned items (default: true).
* @param {Boolean} [options.getGroupItems] - whether to include GroupItems in returned items (default: true).
* @param {Boolean} [options.getLayers] - whether to include Layers in returned items (default: false).
* @param {Boolean} [options.getHiddenItems] - whether to include hidden items in returned items (default: true).
* @param {Boolean} [options.getLockedItems] - whether to include locked items in returned items (default: true).
* @param {Boolean} [options.getGuideItems] - whether to include guide items in returned items (default: false).
* @param {Number} [options.maxDepth] - deepest folder level (recursion depth limit) (default: 99).
* @param {Boolean} [options.returnFirstMatch] - whether to return only the first found item (default: false).
* @param {Number} [depth] - the current depth (private).
* @returns {Array|PageItem} - all the found items in a flat array, or the first found item if `returnFirstMatch`.
*/
function getItems(options, depth) {
// defaults
options = options || {};
var found = [],
depth = depth || 0,
items = options.from;
if (!options.initialized)
// once-off initialization
if (!initialize())
return [];
itemsLoop:
for (var i = 0, item, len = items.length; i < len; i++) {
item = items[i];
if (
false === excludeFilter(item)
&& true === includeFilter(item)
) {
// item found!
found.push(item);
if (options.returnFirstMatch)
break itemsLoop;
}
if (
'GroupItem' !== item.constructor.name
&& 'Layer' !== item.typename
)
// only items with children from here
continue itemsLoop;
if (
excludeHidden(item)
|| excludeLocked(item)
)
// don't look into excluded containers
continue itemsLoop;
if (depth >= options.maxDepth)
// don't go deeper
continue itemsLoop;
// set up for the next depth
options.from = item.pageItems;
// look inside
found = found.concat(getItems(options, depth + 1));
}
// this level done
if (true == options.returnFirstMatch)
return found[0];
else
return found;
/**
* Returns true when the item should be not be found.
* @param {PageItem|Layer} item
* @returns {Boolean}
*/
function excludeFilter(item) {
return (
isAlreadyFound(item)
// is hidden
|| excludeHidden(item)
// is locked
|| excludeLocked(item)
// is guide
|| (
false === options.getGuideItems
&& true === item.guides
)
// is layer
|| (
false === options.getLayers
&& 'Layer' === item.typename
)
// is group item
|| (
false === options.getGroupItems
&& 'GroupItem' === item.typename
)
// is page item
|| (
false === options.getPageItems
&& 'GroupItem' !== item.typename
&& undefined != item.uuid
)
);
};
/**
* Returns true when the item should be included.
* @param {PageItem|Layer} item
* @returns {Boolean}
*/
function includeFilter(item) {
return (
undefined == options.filter
|| options.filter(item, depth)
);
};
/**
* Returns true when the item should
* be excluded because it is hidden.
* @param {PageItem|Layer} item
* @returns {Boolean}
*/
function excludeHidden(item) {
return (
false === options.getHiddenItems
&& (
true === item.hidden
|| false === item.visible
)
);
};
/**
* Returns true when the item should
* be excluded because it is locked.
* @param {PageItem|Layer} item
* @returns {Boolean}
*/
function excludeLocked(item) {
return (
false === options.getLockedItems
&& true === item.locked
);
};
/**
* Returns true if item was already
* found, and marks item as found,
* to avoid finding same item twice.
* @param {PageItem|Layer} item
* @returns {Boolean}
*/
function isAlreadyFound(item) {
var uuid = item.hasOwnProperty('uuid')
? item.uuid
: item.typename + item.zOrderPosition,
isFound = !!options.isFound[uuid];
options.isFound[uuid] = true;
return isFound;
}
/**
* Returns the initialised `options` object.
* @returns {Object}
*/
function initialize() {
// make a new object, so we don't pollute the original
options = {
initialized: true,
depth: 0,
isFound: {},
filter: options.filter,
getPageItems: false !== options.getPageItems,
getGroupItems: false !== options.getGroupItems,
getLayers: true === options.getLayers,
getHiddenItems: false !== options.getHiddenItems,
getLockedItems: false !== options.getLockedItems,
getGuideItems: true === options.getGuideItems,
maxDepth: options.maxDepth,
returnFirstMatch: options.returnFirstMatch,
};
if (
undefined == options.maxDepth
|| !options.maxDepth instanceof Number
)
options.maxDepth = 99;
// items is a single layer
if ('Layer' === items.typename)
items = [items];
// items is a document
else if ('Document' === items.constructor.name) {
var layers = items.layers;
items = [];
for (var i = 0; i < layers.length; i++)
items.push(layers[i]);
}
else if ('Array' !== items.constructor.name)
items = [items];
return items.length > 0;
};
};
Copy link to clipboard
Copied
I should have made it clear that @CarlosCanto's excellent approach is the most efficient way if you know the structure of your document.
- Mark
Find more inspiration, events, and resources on the new Adobe Community
Explore Now