Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

Can you help me modify this script , Change the file name of picture directly to its note.

Guide ,
Jul 27, 2024 Jul 27, 2024


But I just want to modify the content after @, @ and its previous numbers remain unchanged.
For example, this is the end:
P040-001@Great Village Mango Base
Thank you very much ~

how.jpg

 

/*

Links Rename Selected
Copyright 2023 William Campbell
All Rights Reserved
https://www.marspremedia.com/contact

Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

*/

(function () {

    var title = "Rename Selected Links 链接改名";

    if (!/indesign/i.test(app.name)) {
        alert("适用ID", title, false);
        return;
    }

    // Script variables.
    var doc;
    var extension;
    var file;
    var fileNew;
    var i;
    var link;
    var baseName;
    var nameNew;
    var nameOld;
    var selection;

    // SETUP

    if (!app.documents.length) {
        alert("打开文件", title, false);
        return;
    }
    doc = app.activeDocument;

    // EXECUTE

    selection = doc.selection[0];
    if (selection) {
        try {
            if (selection instanceof Rectangle) {
                link = selection.allGraphics[0].itemLink;
            } else {
                link = selection.itemLink;
            }
        } catch (_) {
            // Ignore.
        }
        if (link) {
            nameOld = link.name;
            // Split filename into name and extension.
            baseName = link.name.replace(/\.[^\.]*$/, "");
            extension = String(String(link.name.match(/\..*$/) || "").match(/[^\.]*$/) || "");
            nameNew = prompt("根据需要修改名称\n(扩展保持不变)", baseName, title);
            if (nameNew && nameNew != baseName) {
                // Add back extension.
                nameNew += "." + extension;
                // Test if new name exists.
                fileNew = new File(new File(link.filePath).path + "/" + nameNew);
                if (fileNew.exists) {
                    alert(nameNew + "已经存在", title, true);
                    return;
                }
                // Rename and relink.
                file = new File(link.filePath);
                file.rename(nameNew);
                // Loop through all graphics and relink.
                // Graphic could be placed more than once.
                for (i = 0; i < doc.links.length; i++) {
                    if (doc.links[i].name == nameOld) {
                        doc.links[i].relink(file);
                        doc.links[i].update();
                    }
                }
            }
            return;
        }
    }
    alert("选择放置的图形或其框架", title, false);

})();

 

TOPICS
Bug , Feature request , How to , Performance , Scripting , UXP Scripting
748
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Community Expert , Jul 27, 2024 Jul 27, 2024

Hi @dublove I have written a script that I hope does what you ask. Please give it a try and let me know how it goes. I hope you can follow along in the script to see what I am doing: I locate the caption based on it's proximity to the bottom left of the graphic frame, then rename the link.

- Mark

 

 

/**
 * @file Rename Link With Caption.js
 *
 * Usage:
 *   1. Select one or more graphic frames
 *      (non-graphics will be ignored).
 *   2. Run script
 *
 * If the linked file's name contains "@
...
Translate
Community Expert ,
Jul 27, 2024 Jul 27, 2024

Hi @dublove, is that a Live Caption, or normal text in the frame under the image?

- Mark

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Jul 27, 2024 Jul 27, 2024

Normal text in the frame under the image. It turned out to be generated by static caption, But later modified Several times, it has nothing to do with the original Caption.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jul 27, 2024 Jul 27, 2024

Hi @dublove I have written a script that I hope does what you ask. Please give it a try and let me know how it goes. I hope you can follow along in the script to see what I am doing: I locate the caption based on it's proximity to the bottom left of the graphic frame, then rename the link.

- Mark

 

 

/**
 * @file Rename Link With Caption.js
 *
 * Usage:
 *   1. Select one or more graphic frames
 *      (non-graphics will be ignored).
 *   2. Run script
 *
 * If the linked file's name contains "@" symbol it
 * Will rename the linked file, replacing text after
 * the "@" with the caption of the image, if found.
 *
 * @author m1b
 * @discussion https://community.adobe.com/t5/indesign-discussions/can-you-help-me-modify-this-script-change-the-file-name-of-picture-directly-to-its-note/m-p/14763414
 */
function main() {

    if (0 === app.documents.length)
        return alert('Please open a document and try again.');

    var doc = app.activeDocument,
        items = doc.selection,
        stats = { total: 0, counter: 0 };

    for (var i = items.length - 1, item; i >= 0; i--)
        items[i] = renameLinkWithCaption(items[i], items, stats) || items[i];

    // alert('Renamed ' + stats.counter + ' out of ' + stats.total + ' graphics.');

};
app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Rename Linked File By Caption');

/**
 * Renames the linked graphic file
 * incorporating the graphic's caption.
 * @author m1b
 * @version 2024-07-29
 * @param {Graphic} item - the linked graphic.
 * @param {Array<PageItem>} [items] - the items to search for caption frame (default: all items on page).
 * @param {Object} stats - an object for collecting statistics.
 * @returns {Graphic} - the updated graphic.
 */
function renameLinkWithCaption(item, items, stats) {

    stats = stats || { total: 0, counter: 0 };

    if (
        item
        && !item.hasOwnProperty('itemLink')
        && item.allGraphics
        && item.allGraphics.length
    )
        item = item.allGraphics[0];

    if (
        !item
        || !item.hasOwnProperty('itemLink')
    )
        return;

    stats.total++;

    if (LinkStatus.LINK_MISSING === item.itemLink.status)
        return alert('The graphic is missing. Please re-link and try again.');

    // get the caption for this linked graphic
    var captionFrame = getCaptionTextFrame(item, items);

    if (!captionFrame)
        return alert('Could not locate caption for this link.');

    // clean up the caption suitable for filenaming
    var link = item.itemLink,
        forbiddenChars = /[:\/\\]/g,
        afterTheAtSymbol = /\@(.*)(\.[^\.]+)$/,
        newName = captionFrame.contents
            // sanitize filename
            .replace(forbiddenChars, '')
            // remove file extension, if any
            .replace(/\.[^\.]+$/, '');

    if (!afterTheAtSymbol.test(link.name))
        return alert('Linked file name did not match the expected format (no @ symbol).');

    // incorporate into the existing name
    newName = link.name.replace(afterTheAtSymbol, '@' + newName + '$2');

    if (newName === link.name)
        return;

    // rename the link, get new reference to link and item
    link = renameLink(link, newName);

    if (
        !link
        || !link.isValid
    )
        return;

    item = link.parent;

    stats.counter++;

    return item;

};

/**
 * Renames the a link's *file* and
 * re-links to the renamed file.
 * @author m1b
 * @version 2024-07-28
 * @param {Link} link - the link to rename.
 * @param {String} newName - the name to apply.
 * @return {Link?} - the updated link.
 */
function renameLink(link, newName) {

    var file = File(link.filePath);

    if (!file.exists)
        return;

    var newPath = link.filePath.replace(link.name, newName);

    file.rename(newName);

    link.relink(File(newPath));

    if (link.isValid)
        return link;

};

/**
 * Returns a caption frame, given a page item.
 * @author m1b
 * @version 2024-07-29
 * @param {Page Item} graphic - a linked graphic.
 * @param {Array<PageItem>} [items] - the items to search for caption frame (default: all items on page).
 * @param {Anchor} [graphicAnchor] - an Indesign Anchor (default: AnchorPoint.BOTTOM_CENTER_ANCHOR).
 * @param {Anchor} [captionAnchor] - an Indesign Anchor (default: AnchorPoint.TOP_CENTER_ANCHOR).
 * @returns {TextFrame?}
 */
function getCaptionTextFrame(graphic, items, graphicAnchor, captionAnchor) {

    items = items.slice() || graphic.parent.parentPage.allPageItems;
    graphicAnchor = graphicAnchor || AnchorPoint.BOTTOM_CENTER_ANCHOR;
    captionAnchor = captionAnchor || AnchorPoint.TOP_CENTER_ANCHOR;

    var point = getPointFromBounds(graphic.parent.geometricBounds, graphicAnchor),
        captionFrame;

    // sort by distance from bottom left of graphic frame
    items.sort(sortByDistanceFrom(point, captionAnchor));

    // bypass items with no contents
    do {

        captionFrame = items.shift();

        if (!captionFrame)
            return;

    } while (
        'TextFrame' !== captionFrame.constructor.name
        || !captionFrame.contents
        || captionFrame === graphic.parent
    );

    return captionFrame;

};

/**
 * Returns a sort function which sorts page items by the
 * distance from `point` to an item's anchor point.
 * @param {point} point - [x,y].
 * @param {Anchor} [anchor] - an Indesign Anchor (default: top-left).
 * @returns {Number}
 */
function sortByDistanceFrom(point, anchor) {

    anchor = anchor || AnchorPoint.TOP_LEFT_ANCHOR;

    return function sortByDistanceFromPoint(a, b) {
        var distanceA = mDist(getPointFromBounds(a.geometricBounds, anchor), point),
            distanceB = mDist(getPointFromBounds(b.geometricBounds, anchor), point);
        return distanceA - distanceB;
    };

};

/**
 * Returns the "Manhattan" distance between two points.
 * @param {point} p0 - a point array [x,y].
 * @param {point} p1 - a point array [x,y].
 * @returns {Number}
 */
function mDist(p0, p1) {
    var dx = Math.abs(p1[0] - p0[0]),
        dy = Math.abs(p1[1] - p0[1]);
    return dx + dy;
};

/**
 * Returns a point, given `bounds` and an `anchor`.
 * @author m1b
 * @version 2024-07-28
 * @param {Array<Number>} bounds - bounds [T, L, B, R].
 * @param {Anchor} anchor - an Indesign Anchor.
 * @returns {point} - [x, y].
 */
function getPointFromBounds(bounds, anchor) {

    switch (anchor) {

        case AnchorPoint.TOP_LEFT_ANCHOR:
            return [bounds[1], bounds[0]];

        case AnchorPoint.TOP_CENTER_ANCHOR:
            return [bounds[1] + (bounds[3] - bounds[1]) / 2, bounds[0]];

        case AnchorPoint.TOP_RIGHT_ANCHOR:
            return [bounds[3], bounds[0]];

        case AnchorPoint.CENTER_ANCHOR:
            return [bounds[1] + (bounds[3] - bounds[1]) / 2, bounds[0] + (bounds[2] - bounds[0]) / 2];

        case AnchorPoint.LEFT_CENTER_ANCHOR:
            return [bounds[1], bounds[0] + (bounds[2] - bounds[0]) / 2];

        case AnchorPoint.RIGHT_CENTER_ANCHOR:
            return [bounds[3], bounds[0] + (bounds[2] - bounds[0]) / 2];

        case AnchorPoint.BOTTOM_CENTER_ANCHOR:
            return [bounds[1] + (bounds[3] - bounds[1]) / 2, bounds[2]];

        case AnchorPoint.BOTTOM_LEFT_ANCHOR:
            return [bounds[1], bounds[2]];

        case AnchorPoint.BOTTOM_RIGHT_ANCHOR:
            return [bounds[3], bounds[2]];

        default:
            break;
    }

};

 

 

Edit 2024-07-28: changed structure slightly so that multiple graphics could be selected and renamed at once, and added feedback alert.

 

Edit 2024-07-28: added `getPointFromBounds` function to make it easier for OP to set the measurement points as desired. Edit this line:

 

bottomCenter = getPointFromBounds(bounds, AnchorPoint.BOTTOM_CENTER_ANCHOR),

 

and/or this line:

 

items.sort(sortByDistanceFrom(bottomCenter, AnchorPoint.TOP_CENTER_ANCHOR));

 

 

Edit 2024-07-29: Based on OP feedback, I turned the error alerts back on, I turned off the final stats alert, and now, if the caption contains a file extension, it will remove it before renaming link. Also in this version you must select the caption(s) along with the graphic(s)—script will no longer search for captions outside of the selected page items. To revert this behaviour,  change this line:

 

items[i] = renameLinkWithCaption(items[i], items, stats) || items[i];

 

to:

 

items[i] = renameLinkWithCaption(items[i], undefined, stats) || items[i];

 

 

Edit 2024-07-30: fixed bug where `items` array was being mutated by `getCaptionTextFrame`.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Jul 27, 2024 Jul 27, 2024

Hi~m1b

Thank you very muck.

Select  single picture , it can be run.

If you choose more than two pictures, you will not run anymore.


I suggest to choose pictures and its picture descriptions at the same time, which will be safer.
Only by selecting two pictures and their picture description frameworks, you need to judge which text framework is the recently.

The script runs quietly. At first I was a bit unaccustomed, but have the prompts may be even more uncomfortable.

 

66666.jpg

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jul 28, 2024 Jul 28, 2024

Yes selecting multiple graphics at once is a good idea—I have updated script above.

 

However, the idea to select a graphic and its caption does not help much when you are selecting multiple graphics as the script still has to work out which caption belongs to which graphics.

 

The method I've chosen is quite robust in my opinion—I get the text frame whose top-left is closest to the graphic frame's bottom-left (see graphic below). I cannot imagine a realistic situation where this would fail. Do you have a counter example?

- Mark

Screenshot 2024-07-28 at 19.12.47.png

 

 

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Jul 28, 2024 Jul 28, 2024

Limit the script , even  only modify one image, you need to select both the image and the text frame.
Instead of  now, that just selecting the image  it can run.

 

Even if we select more than 2 images,  We should also select  their caption the frame, But it should not contain other text boxes.

We can only run the script for the selected diagram and frame.
So, at most we can run it for the double page (left and right pages).

There is a clear distance between the image description frames.

625.jpg

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jul 28, 2024 Jul 28, 2024

I have altered the script to make it easier for you to set the measurement points yourself (and I also changed the measurement distance now to between the BOTTOM_CENTRE of graphic and the TOP_CENTER of caption frame. You still haven't shown me a real example of when it fails.

- Mark

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Jul 28, 2024 Jul 28, 2024

Hi~m1b.

Thank you very muck.

I don't have a good negative example, I think limiting the selection of objects and running scripts is enough.
There are some issues with the script:
1. The script doesn't seem very smooth, sometimes freezing for more than ten seconds.
2. If the selected image link is missing, there should be a pop-up prompt.
3. The running result pop-up suddenly feels a bit redundant, I suggest canceling it.(Or a different way of reminding, can it quickly and automatically disappear?)
4. Do not modify the file extensions. (For example, it used to be abc.jpg, but later became abc.jpg.jpg, which can lead to the loss of link relationships)

 

I understand, the extension in my ID caption has not been deleted

But I deleted the extension, tried again, and quickly changed my name.
I changed my name again for testing and found that it was stuck for  30 seconds.

nn.jpg

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jul 29, 2024 Jul 29, 2024

Hi @dublove, I have updated script again.

1. try again, and see if script speed is improved.

2. I have re-instated the alerts.

3. I have turned the last summary alert off.

4. The script now removes file extensions from the caption.

Also, you must now select the caption(s) as well as the graphic(s).

- Mark

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Jul 29, 2024 Jul 29, 2024

This one didn't get jammed.
Selecting only one diagram and its text box works.

Two diagrams together, failed to rename, prompting the following message

It seems that the first image is not renamed

dublove_0-1722258911108.jpeg

 

The full file is available for download here

http://www.fileconvoy.com/dfl.php?id=gb901106666dc223010005571370d5a5e4c5ee2b366

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jul 29, 2024 Jul 29, 2024

Thankyou — it really helps to have a demo file. I've fixed that bug and updated script again. - Mark

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Apr 02, 2025 Apr 02, 2025
LATEST

@m1b 

How can this script be changed to be generic:
Without judging whether there is an “@” or not, directly replace the whole old filename with the text below the image.

I tried to modify the regulars without success。

Thanks.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines