Copy link to clipboard
Copied
Is there a quick and easy way to select/delete all smart objects in a file outside the canvas? I know cropping deletes pixels in a rasterized layer, but it does not affect smart objects. I also know that I can hit "reveal all" in a file, but with the sheer size of the documents I'm working in, doing so creates another aggravating wait time since photoshop has to load all of them visually.
Basically, is there a way to crop a canvas, then select/delete all the smart objects that are entirely off the canvas without doing reveal all? It would save me so much time. Thank you in advance!
Copy link to clipboard
Copied
As i understand it, the end goal is to remove the layers, not select them.
Try this script* to delete all smart objects in a file outside the canvas **:
#target photoshop
var doc = new AM('document'),
lr = new AM('layer'),
units = (new AM('application')).getProperty('rulerUnits').value,
len = doc.getProperty('numberOfLayers'),
smartObjects = [];
for (var i = 1; i <= len; i++) {
if (lr.getProperty('layerSection', i, true).value == 'layerSectionEnd') continue;
if (lr.getProperty('layerKind', i, true) == 5) {
smartObjects.push({
id: id = lr.getProperty('layerID', i, true),
bounds: lr.descToObject(lr.getProperty('bounds', i, true).value)
})
}
}
if (smartObjects.length) {
doc.setRulerUnits('rulerPixels')
docBounds = { top: 0, left: 0, right: doc.getProperty('width'), bottom: doc.getProperty('height'), }
doc.setRulerUnits(units)
var toDelete = []
do { if (!intersect((so = smartObjects.shift()).bounds, docBounds)) toDelete.push(so.id) } while (smartObjects.length)
if (toDelete.length) doc.deleteLayers(toDelete)
}
function intersect(lrA, lrB) {
return (lrB.right < lrA.left || lrB.left > lrA.right) || (lrB.top > lrA.bottom || lrB.bottom < lrA.top) ? false : true
}
function AM(target, order) {
var s2t = stringIDToTypeID,
t2s = typeIDToStringID;
target = target ? s2t(target) : null;
this.getProperty = function (property, id, idxMode) {
property = s2t(property);
(r = new ActionReference()).putProperty(s2t('property'), property);
id != undefined ? (idxMode ? r.putIndex(target, id) : r.putIdentifier(target, id)) :
r.putEnumerated(target, s2t('ordinal'), order ? s2t(order) : s2t('targetEnum'));
return getDescValue(executeActionGet(r), property)
}
this.descToObject = function (d) {
var o = {}
for (var i = 0; i < d.count; i++) {
var k = d.getKey(i)
o[t2s(k)] = getDescValue(d, k)
}
return o
}
this.setRulerUnits = function (units) {
(r = new ActionReference()).putProperty(s2t('property'), s2t('unitsPrefs'));
r.putEnumerated(s2t('application'), s2t('ordinal'), s2t('targetEnum'));
(d = new ActionDescriptor).putReference(s2t('null'), r);
(d1 = new ActionDescriptor).putEnumerated(s2t('rulerUnits'), s2t('rulerUnits'), s2t(units));
d.putObject(s2t('to'), s2t('unitsPrefs'), d1);
executeAction(s2t('set'), d, DialogModes.NO);
}
this.deleteLayers = function (list) {
var r = new ActionReference();
do { r.putIdentifier(s2t('layer'), list.shift()) } while (list.length);
(d = new ActionDescriptor()).putReference(s2t('null'), r);
executeAction(s2t('delete'), d, DialogModes.NO);
}
function getDescValue(d, p) {
switch (d.getType(p)) {
case DescValueType.OBJECTTYPE: return { type: t2s(d.getObjectType(p)), value: d.getObjectValue(p) };
case DescValueType.LISTTYPE: return d.getList(p);
case DescValueType.REFERENCETYPE: return d.getReference(p);
case DescValueType.BOOLEANTYPE: return d.getBoolean(p);
case DescValueType.STRINGTYPE: return d.getString(p);
case DescValueType.INTEGERTYPE: return d.getInteger(p);
case DescValueType.LARGEINTEGERTYPE: return d.getLargeInteger(p);
case DescValueType.DOUBLETYPE: return d.getDouble(p);
case DescValueType.ALIASTYPE: return d.getPath(p);
case DescValueType.CLASSTYPE: return d.getClass(p);
case DescValueType.UNITDOUBLE: return (d.getUnitDoubleValue(p));
case DescValueType.ENUMERATEDTYPE: return { type: t2s(d.getEnumerationType(p)), value: t2s(d.getEnumerationValue(p)) };
default: break;
};
}
}
* save this code to a text file, change its extension to .jsx, place it in the presets folder (Adobe Photoshop\Presets\Scripts\). Restart Photoshop, the script will appear in the File -> Scripts menu, after that manual launch, hotkey launch, recording to the action will be available.
** the script does not use the actual borders of the smart object, but its bounding box. In most cases this will not be a problem, but if you place smart objects close to the corners of the canvas, then the script can ignore such layers.
Copy link to clipboard
Copied
Thanks so much for this! I got an error when trying to run it, though. Thoughts?
Copy link to clipboard
Copied
Yes, there was an error in the code (the code is written for a document that has a background layer ), I fixed it, but perhaps you download it before this moment. Try to copy it again and run it.
Are you using artboards?
Copy link to clipboard
Copied
I do not
Copy link to clipboard
Copied
EDIT 2: fixed a previously made mistake with no background layer, added support for artboards, read bounds from "boundsNoMask" to prevent incorrect definition of the layer size (exclude path objects)
#target photoshop
var doc = new AM('document'),
lr = new AM('layer'),
len = doc.getProperty('numberOfLayers'),
smartObjects = [],
docBounds = [];
for (var i = 1; i <= len; i++) {
if (lr.getProperty('layerSection', i, true).value == 'layerSectionEnd') continue;
if (lr.getProperty('artboardEnabled', i, true)) {
lr.selectLayers([lr.getProperty('layerID', i, true)])
docBounds.push(lr.descToObject(lr.getProperty('artboard').value.getObjectValue(stringIDToTypeID('artboardRect'))))
continue;
}
if ((kind = lr.getProperty('layerKind', i, true)) != 7) {
smartObjects.push({
id: id = lr.getProperty('layerID', i, true),
bounds: kind != 4 ? lr.descToObject(lr.getProperty('boundsNoMask', i, true).value) : lr.descToObject(lr.getProperty('bounds', i, true).value)
})
}
}
if (smartObjects.length) {
if (!docBounds.length) {
var res = doc.getProperty ('resolution')
docBounds = [{ top: 0, left: 0, right: doc.getProperty('width')*res/72, bottom: doc.getProperty('height')*res/72, }]
}
var toSelect = []
do {
var intersected = false,
so = smartObjects.shift();
for (var i = 0; i < docBounds.length; i++) {
if (intersect(so.bounds, docBounds[i]) && !(so.bounds.width==0 && so.bounds.height ==0)) intersected = true; break;
}
if (!intersected) toSelect.push(so.id)
} while (smartObjects.length)
if (toSelect.length) doc.deleteLayers(toSelect)
}
function intersect(lrA, lrB) {
return (lrB.right < lrA.left || lrB.left > lrA.right) || (lrB.top > lrA.bottom || lrB.bottom < lrA.top) ? false : true
}
function AM(target, order) {
var s2t = stringIDToTypeID,
t2s = typeIDToStringID;
target = target ? s2t(target) : null;
this.getProperty = function (property, id, idxMode) {
property = s2t(property);
(r = new ActionReference()).putProperty(s2t('property'), property);
id != undefined ? (idxMode ? r.putIndex(target, id) : r.putIdentifier(target, id)) :
r.putEnumerated(target, s2t('ordinal'), order ? s2t(order) : s2t('targetEnum'));
return getDescValue(executeActionGet(r), property)
}
this.hasProperty = function (property, id, idxMode) {
property = s2t(property);
(r = new ActionReference()).putProperty(s2t('property'), property);
id ? (idxMode ? r.putIndex(target, id) : r.putIdentifier(target, id))
: r.putEnumerated(target, s2t('ordinal'), order ? s2t(order) : s2t('targetEnum'));
return executeActionGet(r).hasKey(property)
}
this.descToObject = function (d) {
var o = {}
for (var i = 0; i < d.count; i++) {
var k = d.getKey(i)
o[t2s(k)] = getDescValue(d, k)
}
return o
}
this.selectLayers = function (list) {
var r = new ActionReference();
do { r.putIdentifier(s2t('layer'), list.shift()) } while (list.length);
(d = new ActionDescriptor()).putReference(s2t('null'), r);
executeAction(s2t('select'), d, DialogModes.NO);
}
this.deleteLayers = function (list) {
var r = new ActionReference();
do { r.putIdentifier(s2t('layer'), list.shift()) } while (list.length);
(d = new ActionDescriptor()).putReference(s2t('null'), r);
executeAction(s2t('delete'), d, DialogModes.NO);
}
function getDescValue(d, p) {
switch (d.getType(p)) {
case DescValueType.OBJECTTYPE: return { type: t2s(d.getObjectType(p)), value: d.getObjectValue(p) };
case DescValueType.LISTTYPE: return d.getList(p);
case DescValueType.REFERENCETYPE: return d.getReference(p);
case DescValueType.BOOLEANTYPE: return d.getBoolean(p);
case DescValueType.STRINGTYPE: return d.getString(p);
case DescValueType.INTEGERTYPE: return d.getInteger(p);
case DescValueType.LARGEINTEGERTYPE: return d.getLargeInteger(p);
case DescValueType.DOUBLETYPE: return d.getDouble(p);
case DescValueType.ALIASTYPE: return d.getPath(p);
case DescValueType.CLASSTYPE: return d.getClass(p);
case DescValueType.UNITDOUBLE: return (d.getUnitDoubleValue(p));
case DescValueType.ENUMERATEDTYPE: return { type: t2s(d.getEnumerationType(p)), value: t2s(d.getEnumerationValue(p)) };
default: break;
};
}
}
Copy link to clipboard
Copied
It worked beautifully, thank you so much!!!
Copy link to clipboard
Copied
Actually, I was mistaken. The script definitely scans through all the layers now, but doesn't seem to delete of them.
Copy link to clipboard
Copied
Do you use masks when working with smart objects? If you select the move tool and turn on the "show transform controls" checkbox, is the smart object completely outside the canvas?
The script only deletes smart objects and ignores other types of layers. Perhaps this is the problem?
Can you send a screenshot of your workspace and layers palette?
PS I updated the code in a previous post (EDIT 2) to ignore the size of layer masks, which can increase SO size significantly.
Copy link to clipboard
Copied
Apologies, as JJMack pointed my terminology could have been clearer. While smart objects are included in my goal, my primary concern is with text objects or any type of layer that isn't rasterized and thus can't be deleted through cropping.
Copy link to clipboard
Copied
I updated EDIT 2 script. Please try again.
Now it deletes all kinds of layers outside canvas (also added special handling to get the size of the shape layers).
Copy link to clipboard
Copied
Cropping changes the document Canvas size the image's Aspect Ratio and size is changes. This effects all layer that have content above the document canvas in the cropped off area. The effect is like deleting the layer's pixels in the cropped off areas. Crop effect all layers. that Photoshop renders pixels for. Photoshop renders pixels for shapes text smars objects all layers with imags content have pixels the are blended into Photoshop composite image. Crop does not delet Layers it can change some layers bounds that is an option you can check in the Crop tool's tool option bar, "Delete Cropped Pisxels" Normal Pixels layer sized can be changed with the optiom checked. Here all Layer 1 Pixels wrere delete by the crop tool the layer has no pixels after crop delete all its pixelsd it did not delete the layer. Layer 1 still exists but is
empty.
Copy link to clipboard
Copied
I tried runnig this one after my comment of your other one (edit 3) deleting most layers but this one worked perfectly! Exactly what I was looking for, thank you so much :))
Copy link to clipboard
Copied
I should probably also mentioned that it's possible the script wasn't working for me was because I was using CC 2018 and failed to include that at any point lol. It works great in 2021, though.
Copy link to clipboard
Copied
Well, it was working great but now I am hitting this error randomly (using 2021):
I appreciate all your help with this script!
Copy link to clipboard
Copied
If you do not care to preserve your work in layers why are you saving layered files? The script jazz-y posted will delete most Smart smart layer that has content that is all off canvas. His diagrams shows the exception case where the smart object layer's content is all off canvas however the layer bounds has some area over the documents canvas with no content.
Smart object layer have high overhead. However, they preserve the object quality. Transforming and warping a smart object layer is none destructive. The object is not changed just the smart objects layer pixels are just a new transformation of the object pixels every time you edit the Smart Object layer's object's transform.
Copy link to clipboard
Copied
Part of my work requires using a massive master file that has text layers all over it, then cropping sections out to create a separate file. Cropping the master file itself takes time, but continuing to work in the new ones, while all the non-rasterized layers sit outside the canvas slows down my workflow. The closest solution I have found is doing 'reveal all' then selecting and deleting the smart objects to speed up photoshop, but doing so adds to the loading time since photoshop has to essentially render them again. Theoretically, I could rasterize the text layers, but it's not ideal.
Copy link to clipboard
Copied
You are confusing me. Smart object layer are not text layers. What are the smart object layer used for? Why do your have smart object layers in you document that do not have content that is visible in the your outpur image files? Why do these smart layer even exists? If preserving the object is quality is not important, Rasterizing all object layer would reduce the master file size and eliminate the smart object layer overhead and cropping the master document to canvas size would delete all content in layers outside the Document canvas. Smart object layers are often use in mockup templates so the object content can be replace and be resize distorted like the smart object in the Mockup template. However some object content is visible in output image files. Cropping Mockups the small parts of the mock does not seem to make sense to me. What are your massine master file normall used for. Why are they created like they have been.
Copy link to clipboard
Copied
Sorry, I should have been more clear. You are correct, text layers are not smart objects; I just consider them to be kind of the 'same' in my mind since they cannot be deleted through the act of cropping. I should have specific that I was meaning both, but primarily text layers, from the start.
Copy link to clipboard
Copied
Since it turned out that my workflow includes such situations, I decided to slightly expand the capabilities of the script, now it:
1. deletes ALL layers whose borders are completely outside the canvas.
2. if after deleting layers empty groups appeared in the document, then it deletes them too
The script tries to find the smallest bounding box in order to take into account (or vice versa, exclude) the effect of the mask (if applied). Also, the script tries to remove the locked layers (and then restore the lock, if after deleting these layers remained inside the canvas)
3. Fixed artboards support
EDIT 3:
#target photoshop
activeDocument.suspendHistory('Remove layers', 'removeLayers()')
function removeLayers() {
var doc = new AM('document'),
lr = new AM('layer'),
lrs = getLayersCollection(doc, lr);
parseLayers(lrs, layers = [], canvas = [], locked = [], lr)
if (layers.length) {
if (!canvas.length) {
var res = doc.getProperty('resolution')
canvas = [{ top: 0, left: 0, right: doc.getProperty('width') * res / 72, bottom: doc.getProperty('height') * res / 72, }]
}
var layersToDelete = []
do {
var intersected = false,
cur = layers.shift();
for (var i = 0; i < canvas.length; i++) {
if (intersect(cur.bounds, canvas[i]) && !(!cur.bounds.top && !cur.bounds.right && !cur.bounds.left && !cur.bounds.right)) { intersected = true; break; }
}
if (!intersected) layersToDelete.push(cur.id)
} while (layers.length)
if (layersToDelete.length) {
doc.deleteLayers(layersToDelete)
lrs = getLayersCollection(doc, lr)
var groupsToDelete = []
cleanupEmptyGroups(lrs, groupsToDelete)
if (groupsToDelete.length) doc.deleteLayers(groupsToDelete)
}
if (locked.length) {
do {
var cur = locked.shift()
try { lr.applyLocking(cur.id, cur.layerLocking) } catch (e) { }
} while (locked.length)
}
}
}
function intersect(lrA, lrB) {
return (lrB.right < lrA.left || lrB.left > lrA.right) || (lrB.top > lrA.bottom || lrB.bottom < lrA.top) ? false : true
}
function parseLayers(layersCollection, layers, canvas, locked, lr) {
for (var i = 0; i < layersCollection.length; i++) {
if (isLocked(layersCollection[i].layerLocking)) {
locked.push({ layerLocking: layersCollection[i].layerLocking, id: layersCollection[i].id })
lr.applyLocking(layersCollection[i].id,
{
"protectAll": false,
"protectArtboardAutonest": false,
"protectComposite": false,
"protectPosition": false,
"protectTransparency": false
})
}
if (layersCollection[i].artboardRect) {
canvas.push(layersCollection[i].artboardRect)
}
if (layersCollection[i].layerKind == 7) {
parseLayers(layersCollection[i], layers, canvas, locked, lr)
} else {
layers.push(layersCollection[i])
}
}
}
function cleanupEmptyGroups(layersCollection, toDelete) {
var isEmpty = true
for (var i = 0; i < layersCollection.length; i++) {
if (layersCollection[i].layerKind == 7 && !layersCollection[i].artboardRect) {
if (layersCollection[i].length) {
if (cleanupEmptyGroups(layersCollection[i], toDelete) && layersCollection.id) toDelete.push(layersCollection.id) else isEmpty = false
} else {
toDelete.push(layersCollection[i].id)
}
} else isEmpty = false
}
return isEmpty
}
function getLayersCollection(document, layer) {
var indexFrom = document.getProperty('hasBackgroundLayer') ? 0 : 1,
indexTo = document.getProperty('numberOfLayers');
return layersCollection(indexFrom, indexTo)
function layersCollection(from, to, parentItem, group) {
parentItem = parentItem ? parentItem : [];
for (var i = from; i <= to; i++) {
if (layer.getProperty('layerSection', i, true).value == 'layerSectionEnd') {
i = layersCollection(i + 1, to, [], parentItem)
continue;
}
var p = {};
p.id = layer.getProperty('layerID', i, true)
p.layerKind = layer.getProperty('layerKind', i, true)
p.layerLocking = layer.descToObject(layer.getProperty('layerLocking', i, true).value)
p.bounds = [layer.descToObject(layer.getProperty('bounds', i, true).value)]
if (layer.hasProperty('boundsNoMask')) p.bounds.push(layer.descToObject(layer.getProperty('boundsNoMask', i, true).value))
if (layer.hasProperty('boundsNoEffects')) p.bounds.push(layer.descToObject(layer.getProperty('boundsNoEffects', i, true).value))
p.bounds = p.bounds.sort(function (a, b) { return (a.right - a.left) + (a.bottom - a.top) > (b.right - b.left) + (b.bottom - b.top) ? 1 : 0 }).shift();
if (p.layerKind == 7 && layer.getProperty('artboardEnabled', i, true)) {
p.artboardRect = layer.descToObject(layer.getProperty('artboard', i, true).value.getObjectValue(stringIDToTypeID('artboardRect')))
}
if (layer.getProperty('layerSection', i, true).value == 'layerSectionStart') {
for (o in p) { parentItem[o] = p[o] }
group.push(parentItem);
return i;
} else {
parentItem.push(p)
}
}
return parentItem
}
}
function isLocked(locking) {
for (var a in locking) {
if (locking[a]) return true
}
return false
}
function AM(target, order) {
var s2t = stringIDToTypeID,
t2s = typeIDToStringID;
target = target ? s2t(target) : null;
this.getProperty = function (property, id, idxMode) {
property = s2t(property);
(r = new ActionReference()).putProperty(s2t('property'), property);
id != undefined ? (idxMode ? r.putIndex(target, id) : r.putIdentifier(target, id)) :
r.putEnumerated(target, s2t('ordinal'), order ? s2t(order) : s2t('targetEnum'));
return getDescValue(executeActionGet(r), property)
}
this.hasProperty = function (property, id, idxMode) {
property = s2t(property);
(r = new ActionReference()).putProperty(s2t('property'), property);
id ? (idxMode ? r.putIndex(target, id) : r.putIdentifier(target, id))
: r.putEnumerated(target, s2t('ordinal'), order ? s2t(order) : s2t('targetEnum'));
return executeActionGet(r).hasKey(property)
}
this.descToObject = function (d) {
var o = {}
for (var i = 0; i < d.count; i++) {
var k = d.getKey(i)
o[t2s(k)] = getDescValue(d, k)
}
return o
}
this.objectToDesc = function (o) {
var d = new ActionDescriptor();
for (var k in o) {
var v = o[k];
switch (typeof (v)) {
case 'boolean': d.putBoolean(s2t(k), v); break;
case 'string': d.putString(s2t(k), v); break;
case 'number': d.putInteger(s2t(k), v); break;
}
}
return d;
}
this.applyLocking = function (id, locking) {
(r = new ActionReference()).putIdentifier(s2t('layer'), id);
(d = new ActionDescriptor()).putReference(s2t('null'), r);
d.putObject(s2t('layerLocking'), s2t('layerLocking'), this.objectToDesc(locking));
executeAction(s2t('applyLocking'), d, DialogModes.NO);
}
this.selectLayers = function (list) {
var r = new ActionReference();
do { r.putIdentifier(s2t('layer'), list.shift()) } while (list.length);
(d = new ActionDescriptor()).putReference(s2t('null'), r);
executeAction(s2t('select'), d, DialogModes.NO);
}
this.deleteLayers = function (list) {
var r = new ActionReference();
do { r.putIdentifier(s2t('layer'), list.shift()) } while (list.length);
(d = new ActionDescriptor()).putReference(s2t('null'), r);
executeAction(s2t('delete'), d, DialogModes.NO);
}
function getDescValue(d, p) {
switch (d.getType(p)) {
case DescValueType.OBJECTTYPE: return { type: t2s(d.getObjectType(p)), value: d.getObjectValue(p) };
case DescValueType.LISTTYPE: return d.getList(p);
case DescValueType.REFERENCETYPE: return d.getReference(p);
case DescValueType.BOOLEANTYPE: return d.getBoolean(p);
case DescValueType.STRINGTYPE: return d.getString(p);
case DescValueType.INTEGERTYPE: return d.getInteger(p);
case DescValueType.LARGEINTEGERTYPE: return d.getLargeInteger(p);
case DescValueType.DOUBLETYPE: return d.getDouble(p);
case DescValueType.ALIASTYPE: return d.getPath(p);
case DescValueType.CLASSTYPE: return d.getClass(p);
case DescValueType.UNITDOUBLE: return (d.getUnitDoubleValue(p));
case DescValueType.ENUMERATEDTYPE: return { type: t2s(d.getEnumerationType(p)), value: t2s(d.getEnumerationValue(p)) };
default: break;
};
}
}
Copy link to clipboard
Copied
: )
Чё-то у меня удаляет всё подряд. Пустые группы, кстати, не удаляет.
Думаю, лучше поверять видимость слоя в пределах канваса, делая калькуляцию слоя в выделение и проверяя пересечение его (выделения) с выделением канваса.
Если слой сгуппирован со слоем вне канваса, то это проблема (без решнния пока, облом соображать...: )
Copy link to clipboard
Copied
Это норма Ⓒ 🙂
Я писал под последний шоп и совершенно забыл, что свойства width и height в дескрипторе bounds появились не так давно. Насколько понимаю, проблемы были из-за этого. Немного поправил код.
Группы удаляет в теле функции удаления слоев, т.е. если скрипту нечего удалять за канвасом, то он их не трогает. Наверное надо было сделать немного по-другому.
П.С. пока тестировал, обнаружил у себя документ с неудаляемой группой (т.е. ее реально никак не удалить - ни через интерфейс, ни через скрипт). Файл создан вручную (не скриптом), не поврежден. Вот кроп из него: неудаляемая группа
Copy link to clipboard
Copied
I used 'drag & drop' option for your .psd (up to 47 MB).
It's good when other link is going to be broken one day.
Copy link to clipboard
Copied
Это норма Ⓒ 🙂
Я писал под последний шоп и совершенно забыл, что свойства width и height в дескрипторе bounds появились не так давно. Насколько понимаю, проблемы были из-за этого. Немного поправил код.
Группы удаляет в теле функции удаления слоев, т.е. если скрипту нечего удалять за канвасом, то он их не трогает. Наверное надо было сделать немного по-другому.
П.С. пока тестировал, обнаружил у себя документ с неудаляемой группой (т.е. ее реально никак не удалить - ни через интерфейс, ни через скрипт). Файл создан вручную (не скриптом), не поврежден. Вот кроп из него: неудаляемая группа
By @jazz-y
Всё идёт по плану (с) : )
В 2020 всё есть в bounds слоя, и width и height. Но у меня удаляет все слои рамер (и положение) которых не совпадает с канвасом. Ковырять код и разбираться некогда. Может потом как-нибудь...
P.S. Файл прикольный. Где-то я уже видел на форуме такой, точно с такой же проблемой.
Тоже поковыряю на досуге, интересно в чём причина.
Copy link to clipboard
Copied
По поводу файла.
Здесь у layerSectionEnd стоит layerLocking.protectAll = true.
Стандартным способом (скриптом) сбросить его не удаётся.
В метаданных сказано, что файл создан CS5.1. Может он глючный (CS5.1) был и лочил layerSectionEnd когда ставили замок, не могу проверить.
Папка удаляется на раз через Ungroup. Но это не выход.