# How to edit Session Token's file name?

**URL:** <https://forums.creativeclouddeveloper.com/t/how-to-edit-session-tokens-file-name/6450>\
**Category:** UXP Plugin API\
**Created:** [June 29, 2023, 1:04pm UTC](https://forums.creativeclouddeveloper.com/t/how-to-edit-session-tokens-file-name/6450 "2023-06-29T13:04:01Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![joooopeeee](https://avatars.discourse-cdn.com/v4/letter/j/91b2a8/32.png) [@joooopeeee](https://forums.creativeclouddeveloper.com/u/joooopeeee)\
**Post date:** [June 29, 2023, 1:04pm UTC](https://forums.creativeclouddeveloper.com/t/how-to-edit-session-tokens-file-name/6450/1 "2023-06-29T13:04:01Z")

</div>

Hey all,  
Is there a way to edit the sessions token’s file name? I am exporting jpgs using batchplay and for \_path, I am using session token. However my script needs to be able to modify the file name (ex. adding prefix or suffix). It seems like the \_name of the session token is read only. is there any other way to modify it?  
Thank you all in advance

return await batchPlay(  
[  
{  
\_obj: “save”,  
as: {  
\_obj: “JPEG”,  
extendedQuality: jpgQuality,  
matteColor: {  
\_enum: “matteColor”,  
\_value: “none”  
}  
},  
in: {  
\_path: token,  
\_kind: “local”  
},  
lowerCase: true,  
saveStage: {  
\_enum: “saveStageType”,  
\_value: “saveBegin”  
},  
\_isCommand: false  
}  
],  
{}  
);

---

<div class="post-metadata">

**Author:** ![Timothy\_Bennett](https://sea1.discourse-cdn.com/flex015/user_avatar/forums.creativeclouddeveloper.com/timothy_bennett/32/1251_2.png) [@Timothy\_Bennett](https://forums.creativeclouddeveloper.com/u/Timothy_Bennett)\
**Post date:** [June 29, 2023, 1:22pm UTC](https://forums.creativeclouddeveloper.com/t/how-to-edit-session-tokens-file-name/6450/2 "2023-06-29T13:22:42Z")

</div>

You want to generate a new token for each instance, for example by calling a generic save utility function , something like this:

```auto
const saveJPEG = async (saveFolder, newFilename, quality) => {
  try {
    const doc = app.activeDocument;

    const theNewFile = await saveFolder.createFile(newFilename, {
      overwrite: true,
    });
    const saveFile = await fs.createSessionToken(theNewFile);

    return batchPlay(
      [
        {
          _obj: "save",
          as: {
            _obj: "JPEG",
            extendedQuality: quality,
            matteColor: {
              _enum: "matteColor",
              _value: "none",
            },
          },
          in: {
            _path: saveFile,
            _kind: "local",
          },
          documentID: doc.id,
          lowerCase: true,
          saveStage: {
            _enum: "saveStageType",
            _value: "saveBegin",
          },
          _isCommand: true,
          _options: {
            dialogOptions: "dontDisplay",
          },
        },
      ],
      {}
    );
  } catch (error) {
    console.log("JPEG save failed")
    console log(error);
  }
};

```

---

<div class="post-metadata">

**Author:** ![joooopeeee](https://avatars.discourse-cdn.com/v4/letter/j/91b2a8/32.png) [@joooopeeee](https://forums.creativeclouddeveloper.com/u/joooopeeee)\
**Post date:** [June 29, 2023, 2:12pm UTC](https://forums.creativeclouddeveloper.com/t/how-to-edit-session-tokens-file-name/6450/3 "2023-06-29T14:12:09Z")

</div>

Thank you so much Timothy. I am having trouble generating new token from string path. I tried the script you provided. I can see that this script is using createFile but I am not using the getFolder() from ‘localFileSystem’. Is there a way to make tokens from string path and filename? I tried generate new tokens using ‘createEntryWithUrl’ but I couldn’t figure it out!

---

<div class="post-metadata">

**Author:** ![Timothy\_Bennett](https://sea1.discourse-cdn.com/flex015/user_avatar/forums.creativeclouddeveloper.com/timothy_bennett/32/1251_2.png) [@Timothy\_Bennett](https://forums.creativeclouddeveloper.com/u/Timothy_Bennett)\
**Post date:** [June 29, 2023, 2:48pm UTC](https://forums.creativeclouddeveloper.com/t/how-to-edit-session-tokens-file-name/6450/4 "2023-06-29T14:48:20Z")

</div>

`createSessionToken()` receives an [`entry`](https://developer.adobe.com/photoshop/uxp/2022/uxp-api/reference-js/Modules/uxp/Persistent%20File%20Storage/Entry/) and not a `string`.

What’s your workflow?  
E.g. where are your string paths coming from? Collated from open documents? Or from a list of files in a folder?

---

<div class="post-metadata">

**Author:** ![joooopeeee](https://avatars.discourse-cdn.com/v4/letter/j/91b2a8/32.png) [@joooopeeee](https://forums.creativeclouddeveloper.com/u/joooopeeee)\
**Post date:** [June 29, 2023, 3:04pm UTC](https://forums.creativeclouddeveloper.com/t/how-to-edit-session-tokens-file-name/6450/5 "2023-06-29T15:04:27Z")

</div>

I understand. My first entry comes from ‘fs.getFileForSaving’. this is what my script does:

- new file using fs.getFileForSaving
- make changes to the image
- export jpg (filename-V1)
- make further changes to the image
- export jpg under same folder (filename-V2)

The reason I used getFileForSaving instead of getFolder is to get the base filename from the user.  
but aside from that I would love to be able to either generate new entry from a string path. I tried ‘createEntryWithUrl’ but I cannot make it work for the life of me!  
anytime I use it I get this error:  
 ![image](https://us1.discourse-cdn.com/flex015/uploads/xdplugins/original/2X/e/efbfb66bd3cb111d9236d6ca6443998950fc6c29.png)

---

<div class="post-metadata">

**Author:** ![dotproduct](https://avatars.discourse-cdn.com/v4/letter/d/258eb7/32.png) [@dotproduct](https://forums.creativeclouddeveloper.com/u/dotproduct)\
**Post date:** [June 29, 2023, 4:17pm UTC](https://forums.creativeclouddeveloper.com/t/how-to-edit-session-tokens-file-name/6450/6 "2023-06-29T16:17:11Z")

</div>

I think this becomes clear in the error message. Just to double check, have you checked whether the root of said path actually exists? ‘/Users/user’ looks like a generic example path to me. I think you need to construct this path, e.g. using ‘ **os** ’ module’s **homedir()** function. (Unless of course if your user name happens to be ‘user’)

---

<div class="post-metadata">

**Author:** ![Timothy\_Bennett](https://sea1.discourse-cdn.com/flex015/user_avatar/forums.creativeclouddeveloper.com/timothy_bennett/32/1251_2.png) [@Timothy\_Bennett](https://forums.creativeclouddeveloper.com/u/Timothy_Bennett)\
**Post date:** [June 29, 2023, 4:47pm UTC](https://forums.creativeclouddeveloper.com/t/how-to-edit-session-tokens-file-name/6450/7 "2023-06-29T16:47:47Z")

</div>

To clarify, would you like to:

A)  
• open user selected file  
• perform edits to file  
• save file  
• perform more edits  
• save file  
End result: 3 files

Or

B)  
• create new file  
• open new file  
• perform edits to file  
• save file  
• perform more edits  
• save file  
End result: 2 files

---

<div class="post-metadata">

**Author:** ![joooopeeee](https://avatars.discourse-cdn.com/v4/letter/j/91b2a8/32.png) [@joooopeeee](https://forums.creativeclouddeveloper.com/u/joooopeeee)\
**Post date:** [June 29, 2023, 8:13pm UTC](https://forums.creativeclouddeveloper.com/t/how-to-edit-session-tokens-file-name/6450/8 "2023-06-29T20:13:38Z")

</div>

thanks for the help. That was my first guess as well. but no matter what I do it seems like I cannot get the right syntax for the file address. (I tried both mac and windows). Do you happen to know what’s the right syntax for file path?

---

<div class="post-metadata">

**Author:** ![joooopeeee](https://avatars.discourse-cdn.com/v4/letter/j/91b2a8/32.png) [@joooopeeee](https://forums.creativeclouddeveloper.com/u/joooopeeee)\
**Post date:** [June 29, 2023, 8:24pm UTC](https://forums.creativeclouddeveloper.com/t/how-to-edit-session-tokens-file-name/6450/9 "2023-06-29T20:24:17Z")

</div>

Thanks Timothy.  
I am trying to do A. Sorry for being a bit vague. I was trying to avoid boring you with the complete function of my script!  
The function of my script is to export every frame of the timeline (as a copy) into individual jpgs and tiffs. which is why I am exporting every frame with a base name and a sequencer. I get the base name from “getFileForSaving” and repeat the base for every frame. Except I don’t want the user to enter the file name for every frame! I was going to use the SaveAs property of the document but I won’t be able to export tiff as well. if I can get the “createEntryWithUrl” to work I can use the \_nativepath from the entry and modify the name for every frame.  
appologies in advance for the long post!  
p.s: I am aware of image sequencer but that’s limited to 5000px and I need to have more control.

---

<div class="post-metadata">

**Author:** ![dotproduct](https://avatars.discourse-cdn.com/v4/letter/d/258eb7/32.png) [@dotproduct](https://forums.creativeclouddeveloper.com/u/dotproduct)\
**Post date:** [June 29, 2023, 11:01pm UTC](https://forums.creativeclouddeveloper.com/t/how-to-edit-session-tokens-file-name/6450/10 "2023-06-29T23:01:13Z")

</div>

As far as **createEntryWithURL** goes, all the information is in the error message. It wasn’t able to find the path to ‘/Users/user/Documents’ because that doesn’t exist unless your user name on the Mac you’re trying this out happens to be ‘user’. It’s just a matter of specifying a correct path. So, rather than:

`"file:/Users/user/Documents/tmp"` it should be `"file:/Users/YOUR_USERNAME/Documents/tmp"`

Obviously you don’t want to hard-code this. And my guess would be this would be different on Windows. The right thing to do here is to construct this path using the ‘os’ module (described [here](https://developer.adobe.com/photoshop/uxp/2022/uxp-api/reference-js/Modules/os/OS/)) and its function ‘homedir()’

So something like this:

```auto
// Construct file path from os.homedir:
const filePath = path.join(os.homedir(), "Documents", "tmp");
const file = await fs.createEntryWithUrl(`file:${filePath}`)

```

I say ‘like’ because I haven’t tested this, but it should give you an idea on what to do… 🙂

---

<div class="post-metadata">

**Author:** ![joooopeeee](https://avatars.discourse-cdn.com/v4/letter/j/91b2a8/32.png) [@joooopeeee](https://forums.creativeclouddeveloper.com/u/joooopeeee)\
**Post date:** [June 30, 2023, 12:00am UTC](https://forums.creativeclouddeveloper.com/t/how-to-edit-session-tokens-file-name/6450/11 "2023-06-30T00:00:46Z")

</div>

thank you very much. 🙂  
I will try this out and let you know the result.

---

<div class="post-metadata">

**Author:** ![Timothy\_Bennett](https://sea1.discourse-cdn.com/flex015/user_avatar/forums.creativeclouddeveloper.com/timothy_bennett/32/1251_2.png) [@Timothy\_Bennett](https://forums.creativeclouddeveloper.com/u/Timothy_Bennett)\
**Post date:** [June 30, 2023, 1:42am UTC](https://forums.creativeclouddeveloper.com/t/how-to-edit-session-tokens-file-name/6450/12 "2023-06-30T01:42:22Z")

</div>

I’ve [posted](http://forums.creativeclouddeveloper.com/t/batchplay-layer-visibility-nested-smart-objects-bitmap-halftone-saving-closing-oh-my/6267/24) about this before in detail, but essentially you need a token for the folder you want to save to.  
In that post I’m giving the example of getting a folder entry/token via `getFolder()` and then using `getEntries()` to get an array of the folder contents - your use case is different in that your starting point is a file and you want the parent folder.  
You’ve got two choices:

1. prompt the user for a save destination with `getFolder()`
2. use `getEntryWithUrl()` using the path of the active document to get an entry and bypass any user input

I’d say that 2 is what you want from a UX perspective, but as you can [see](http://forums.creativeclouddeveloper.com/t/getentrywithurl/6453) I’m perhaps not the best person to comment on that 😭

---

<div class="post-metadata">

**Author:** ![joooopeeee](https://avatars.discourse-cdn.com/v4/letter/j/91b2a8/32.png) [@joooopeeee](https://forums.creativeclouddeveloper.com/u/joooopeeee)\
**Post date:** [June 30, 2023, 3:32am UTC](https://forums.creativeclouddeveloper.com/t/how-to-edit-session-tokens-file-name/6450/13 "2023-06-30T03:32:35Z")

</div>

Thank you so much mate. appreciate all your helps.  
I will definitely give this a try

---

<div class="post-metadata">

**Author:** ![Timothy\_Bennett](https://sea1.discourse-cdn.com/flex015/user_avatar/forums.creativeclouddeveloper.com/timothy_bennett/32/1251_2.png) [@Timothy\_Bennett](https://forums.creativeclouddeveloper.com/u/Timothy_Bennett)\
**Post date:** [June 30, 2023, 12:55pm UTC](https://forums.creativeclouddeveloper.com/t/how-to-edit-session-tokens-file-name/6450/14 "2023-06-30T12:55:09Z")

</div>

Here you go, a rough demo of what you want.  
It bypasses user input and gets an `entry` for the opened file’s parent folder using `getEntryWithUrl()` and then generates a session token for each jpeg as it saves them.

```auto
const { app, core } = require("photoshop");
const batchPlay = require("photoshop").action.batchPlay;
const lfs = require("uxp").storage.localFileSystem;

try {
  // Helper functions
  const getParentFolderEntry = async (filepath) => {
    const folderPath = path.dirname(filepath);
    return await lfs.getEntryWithUrl(folderPath);
  };

  const getAnimationFrameCount = async () => {
    return await batchPlay(
      [
        {
          _obj: "get",
          _target: [
            {
              _property: "frameCount",
            },
            {
              _ref: "animationClass",
              _enum: "ordinal",
              _value: "targetEnum",
            },
          ],
          _options: {
            dialogOptions: "dontDisplay",
          },
        },
      ],
      {}
    );
  };

 const selectAnimationFrame = async (index) => {
    return await batchPlay(
      [
        {
          _obj: "select",
          _target: [
            {
              _ref: "animationFrameClass",
              _index: index,
            },
          ],
          _options: {
            dialogOptions: "dontDisplay",
          },
        },
      ],
      {}
    );
  };

  const makeSnapshot = async (name) => {
    return batchPlay(
      [
        {
          _obj: "make",
          _target: [
            {
              _ref: "snapshotClass",
            },
          ],
          from: {
            _ref: "historyState",
            _property: "currentHistoryState",
          },
          name: name,
          using: {
            _enum: "historyState",
            _value: "fullDocument",
          },
          _isCommand: true,
          _options: {},
        },
      ],
      {}
    );
  };

  const revertToSnapshot = async (name) => {
    return batchPlay(
      [
        {
          _obj: "select",
          _target: [
            {
              _ref: "snapshotClass",
              _name: name,
            },
          ],
          _isCommand: true,
          _options: {
            dialogOptions: "dontDisplay",
          },
        },
      ],
      {}
    );
  };

  const deleteSnapshot = async (name) => {
    return batchPlay(
      [
        {
          _obj: "delete",
          _target: [
            {
              _ref: "historyState",
              _name: name,
            },
          ],
          _isCommand: true,
          _options: {
            dialogOptions: "dontDisplay",
          },
        },
      ],
      {}
    );
  };

  const saveJPEG = async (saveFolder, newFilename, quality) => {
    try {
      const doc = app.activeDocument;
      const theNewFile = await saveFolder.createFile(newFilename, {
        overwrite: true,
      });
      const saveFile = await lfs.createSessionToken(theNewFile);
       return batchPlay(
        [
          {
            _obj: "save",
            as: {
              _obj: "JPEG",
              extendedQuality: quality,
              matteColor: {
                _enum: "matteColor",
                _value: "none",
              },
            },
            in: {
              _path: saveFile,
              _kind: "local",
            },
            documentID: doc.id,
            lowerCase: true,
            saveStage: {
              _enum: "saveStageType",
              _value: "saveBegin",
            },
            _isCommand: true,
            _options: {
              dialogOptions: "dontDisplay",
            },
          },
        ],
        {}
      );
    } catch (error) {
      console.log(error);
    }
  };

  // Main process
  await core.executeAsModal(async () => {
    const file = await lfs.getFileForOpening();
    const saveFolder = await getParentFolderEntry(file.nativePath);
     await app.open(file);
     const doc = app.activeDocument;
     const baseFilename = doc.name.slice(0, doc.name.lastIndexOf("."));

     const countFrames = await getAnimationFrameCount();

     const frameCount = countFrames[0].frameCount;

     for (let i = 0; i < frameCount; i++) {
       const newFilename = `${baseFilename}_${i + 1}`;

       await selectAnimationFrame(i + 1);

       await makeSnapshot(newFilename);

       doc.flatten();

       await saveJPEG(saveFolder, newFilename, 12);

       await revertToSnapshot(newFilename);

       await deleteSnapshot(newFilename);
     }
   });
 } catch (error) {
   console.error(error);
   console.trace(error);
 }

```

You’ll also need to have your `manifest` conform to v5 like so:

```auto
{
  "host": [
    {
      "app": "PS",
      "minVersion": "24.6.2",
      "data": {
        "apiVersion": 2
      }
    }
  ],
  "manifestVersion": 5,
   "requiredPermissions": {
    "localFileSystem": "fullAccess"
  }
  // ...all other manifest properties
}

```
