# Save multiple documents in subfolder

**URL:** <https://forums.creativeclouddeveloper.com/t/save-multiple-documents-in-subfolder/5776>\
**Category:** Photoshop\
**Created:** [January 31, 2023, 2:03pm UTC](https://forums.creativeclouddeveloper.com/t/save-multiple-documents-in-subfolder/5776 "2023-01-31T14:03:47Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![PS-fxrios](https://sea1.discourse-cdn.com/flex015/user_avatar/forums.creativeclouddeveloper.com/ps-fxrios/32/2461_2.png) [@PS-fxrios](https://forums.creativeclouddeveloper.com/u/PS-fxrios)\
**Post date:** [January 31, 2023, 2:03pm UTC](https://forums.creativeclouddeveloper.com/t/save-multiple-documents-in-subfolder/5776/1 "2023-01-31T14:03:47Z")

</div>

Once I create a persistent teken for a directory and inside that directory I add a subfolder that receives the active document that I save in.tiff format, but I cannot save the other documents, as I receive an Error: A Folder with given name exists . Cannot overwrite a Folder.  
How do I fix this and save the next documents inside the subfolder??

  
js:

```auto
try {
	const fs = require('uxp').storage.localFileSystem;
	// const directory = await fs.getFolder(); //abre uma tela que permite escolher a pasta
	// const persistentToken = await fs.createPersistentToken(directory);//cria um token persistente para a pasta
	// localStorage.setItem('directory', JSON.stringify(persistentToken)); //associa o token criado à entrada da pasta

	token = await JSON.parse(localStorage.getItem("directory")); //selecione o token salvo
	const folder = await fs.getEntryForPersistentToken(token); //extrai o caminho da pasta persistente
	const subfolder = await folder.createFolder("SubFolder"); //Crie as pastas e subpastas desejadas)
	
	const newfile = app.activeDocument.name;
	//cria o arquivo em modo modal
	await core.executeAsModal(async () => {  
		const newFile = await subfolder.createFile(newfile, { overwrite: true });
		const saveFile = await fs.createSessionToken(newFile);
		await app.batchPlay([{"_obj": "save","as":{"_obj": "TIFF","byteOrder":{"_enum": "platform","_value": "IBMPC"},"layerCompression":{"_enum": "encoding","_value": "RLE"}},"in": {"_path": saveFile,"_kind": "local"}}], { });
	});
} 
catch (e) {console.log(e);}	

```

---

<div class="post-metadata">

**Author:** ![Karmalakas](https://sea1.discourse-cdn.com/flex015/user_avatar/forums.creativeclouddeveloper.com/karmalakas/32/1048_2.png) [@Karmalakas](https://forums.creativeclouddeveloper.com/u/Karmalakas)\
**Post date:** [January 31, 2023, 2:46pm UTC](https://forums.creativeclouddeveloper.com/t/save-multiple-documents-in-subfolder/5776/2 "2023-01-31T14:46:39Z")

</div>

If you call this piece of code on every file, it tries to `await folder.createFolder("SubFolder");` also every time

---

<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:** [January 31, 2023, 2:51pm UTC](https://forums.creativeclouddeveloper.com/t/save-multiple-documents-in-subfolder/5776/3 "2023-01-31T14:51:26Z")

</div>

I actually provided a “find or create folder” helper function in another thread a few days ago:

> [@Check directory existence](http://forums.creativeclouddeveloper.com/t/check-directory-existence/5742/11):
>
> Looks good to me. As you’re now duplicating code it would be better to wrap it all up into a helper function. const findOrCreateFolder = async (parentFolder, folderName) =\> { const entries = await parentFolder.getEntries(); const foundFolder = entries.filter((entry) =\> entry.isFolder).find((subFolder) =\> subFolder.name === folderName); if (foundFolder) { return foundFolder } return await parentFolder.createFolder(folderName) }

---

<div class="post-metadata">

**Author:** ![PS-fxrios](https://sea1.discourse-cdn.com/flex015/user_avatar/forums.creativeclouddeveloper.com/ps-fxrios/32/2461_2.png) [@PS-fxrios](https://forums.creativeclouddeveloper.com/u/PS-fxrios)\
**Post date:** [January 31, 2023, 3:04pm UTC](https://forums.creativeclouddeveloper.com/t/save-multiple-documents-in-subfolder/5776/4 "2023-01-31T15:04:41Z")

</div>

I confess that this process to import, save or export files in UXP plugins is my biggest challenge, I’m not familiar with it and I’m willing to face it head on with my rough questions.  
@Timothy_Bennett I read this topic several times, but I couldn’t do it the way you found it, the process of verifying the existence of the subfolder.  
That’s all I managed to do, but to no avail!

```auto
try {
	 const fs = require('uxp').storage.localFileSystem;
	// const directory = await fs.getFolder(); //abre uma tela que permite escolher a pasta
	// const persistentToken = await fs.createPersistentToken(directory);//cria um token persistente para a pasta
	// localStorage.setItem('directory', JSON.stringify(persistentToken)); //associa o token criado à entrada da pasta

	token = await JSON.parse(localStorage.getItem("directory")); //selecione o token salvo
	const folder = await fs.getEntryForPersistentToken(token); //extrai o caminho da pasta persistente
    		const entries = await folder.getEntries();
	const checkSubfolder = entries.filter((entry) => entry.isFolder).find((subFolder) => subFolder.name === "SubFolder");
	
	if (!checkSubfolder) {
		const subfolder = await folder.createFolder("SubFolder"); //Crie as pastas e subpastas desejadas)
	}

	const newfile = app.activeDocument.name;
	//cria o arquivo em modo modal
	await core.executeAsModal(async () => {  
		const newFile = await subfolder.createFile(newfile, { overwrite: true });
		const saveFile = await fs.createSessionToken(newFile);
		await app.batchPlay([{"_obj": "save","as":{"_obj": "TIFF","byteOrder":{"_enum": "platform","_value": "IBMPC"},"layerCompression":{"_enum": "encoding","_value": "RLE"}},"in": {"_path": saveFile,"_kind": "local"}}], { });
	});
} 
catch (e) {console.log(e);}

```

The script verifies, creates but does not save the file  
log

```auto
ReferenceError: subfolder is not defined

```

---

<div class="post-metadata">

**Author:** ![PS-fxrios](https://sea1.discourse-cdn.com/flex015/user_avatar/forums.creativeclouddeveloper.com/ps-fxrios/32/2461_2.png) [@PS-fxrios](https://forums.creativeclouddeveloper.com/u/PS-fxrios)\
**Post date:** [January 31, 2023, 3:52pm UTC](https://forums.creativeclouddeveloper.com/t/save-multiple-documents-in-subfolder/5776/5 "2023-01-31T15:52:30Z")

</div>

I modified this code but it doesn’t save, just create a subfolder. Please, can anyone help me?

```auto
try {
 const fs = require('uxp').storage.localFileSystem;
// const directory = await fs.getFolder(); //abre uma tela que permite escolher a pasta
// const persistentToken = await fs.createPersistentToken(directory);//cria um token persistente para a pasta
// localStorage.setItem('directory', JSON.stringify(persistentToken)); //associa o token criado à entrada da pasta

token = await JSON.parse(localStorage.getItem("directory")); //selecione o token salvo
const folder = await fs.getEntryForPersistentToken(token); //extrai o caminho da pasta persistente

const findOrCreateFolder = async (parentFolder, folderName) => {
	 const entries = await parentFolder.getEntries();
 
	 const foundFolder = entries.filter((entry) => entry.isFolder).find((subFolder) => subFolder.name === folderName);
 
	 if (foundFolder) {
		 return foundFolder
	 }
	 return await parentFolder.createFolder(folderName)
 }

 const main = async () => {
	// The findOrCreateFolder function and all other code goes here - including whatever defines the folder variable that is going to be passed to findOrCreateFolder 
	const theFolder = await findOrCreateFolder(folder, "SubFolder");
 }
 
 main();

const newfile = app.activeDocument.name;
//cria o arquivo em modo modal
await core.executeAsModal(async () => {  
	const newFile = await theFolder.createFile(newfile, { overwrite: true });
	const saveFile = await fs.createSessionToken(newFile);
	await app.batchPlay([{"_obj": "save","as":{"_obj": "TIFF","byteOrder":{"_enum": "platform","_value": "IBMPC"},"layerCompression":{"_enum": "encoding","_value": "RLE"}},"in": {"_path": saveFile,"_kind": "local"}}], { });
});
} 
catch (e) {console.log(e);}

```

---

<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:** [January 31, 2023, 4:20pm UTC](https://forums.creativeclouddeveloper.com/t/save-multiple-documents-in-subfolder/5776/6 "2023-01-31T16:20:22Z")

</div>

Your problem in both examples is one of [scope](https://www.w3schools.com/js/js_scope.asp), but let’s just debug your first example.

The `subfolder` variable is only scoped to your `if` statement and so it doesn’t exist by the time you call it.

If you changed it to this then `subfolder` will still exist when you call and will have a value.

```auto
// Initialize subfolder in global scope, and as a let so it's value can updated later.
// If .find doesn't find a matching folder name it returns undefined 
let subfolder = entries.filter((entry) => entry.isFolder).find((subFolder) => subFolder.name === "SubFolder");

// If subfolder is undefined then create it and assign to subfolder let
if (!subfolder) {
   subfolder = await folder.createFolder("SubFolder"); 
}

// subfolder continues to exist in global scope and cannot be undefined 

```

---

<div class="post-metadata">

**Author:** ![PS-fxrios](https://sea1.discourse-cdn.com/flex015/user_avatar/forums.creativeclouddeveloper.com/ps-fxrios/32/2461_2.png) [@PS-fxrios](https://forums.creativeclouddeveloper.com/u/PS-fxrios)\
**Post date:** [January 31, 2023, 4:36pm UTC](https://forums.creativeclouddeveloper.com/t/save-multiple-documents-in-subfolder/5776/7 "2023-01-31T16:36:12Z")

</div>

Hi @Timothy_Bennett now it worked perfectly! The understanding became much clearer! Thanks for sharing your knowledge.  
I’ll post the script for anyone who needs it.

```auto
try {
	 const fs = require('uxp').storage.localFileSystem;
	// const directory = await fs.getFolder(); //abre uma tela que permite escolher a pasta
	// const persistentToken = await fs.createPersistentToken(directory);//cria um token persistente para a pasta
	// localStorage.setItem('directory', JSON.stringify(persistentToken)); //associa o token criado à entrada da pasta
	token = await JSON.parse(localStorage.getItem("directory")); //selecione o token salvo
	const folder = await fs.getEntryForPersistentToken(token); //extrai o caminho da pasta persistente

            const entries = await folder.getEntries();
	let subfolder = entries.filter((entry) => entry.isFolder).find((subFolder) => subFolder.name === "SubFolder");

	// If subfolder is undefined then create it and assign to subfolder let
	if (!subfolder) {
		subfolder = await folder.createFolder("SubFolder"); 
	}

	const newfile = app.activeDocument.name;
	//cria o arquivo em modo modal
	await core.executeAsModal(async () => {  
		const newFile = await subfolder.createFile(newfile, { overwrite: true });
		const saveFile = await fs.createSessionToken(newFile);
		await app.batchPlay([{"_obj": "save","as":{"_obj": "TIFF","byteOrder":{"_enum": "platform","_value": "IBMPC"},"layerCompression":{"_enum": "encoding","_value": "RLE"}},"in": {"_path": saveFile,"_kind": "local"}}], { });
	});
} 
catch (e) {console.log(e);}

```

---

<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:** [January 31, 2023, 4:59pm UTC](https://forums.creativeclouddeveloper.com/t/save-multiple-documents-in-subfolder/5776/8 "2023-01-31T16:59:24Z")

</div>

Even better would be to wrap all that up in a helper function that you can reuse at any time, for any folder, in any UXP plugin as per the post I linked.

You actually do that successfully in your second example, but it’s all encapsulated in, or rather _scoped_ to, the `main` function and so `theFolder` no longer exists by the time you call it to save.  
In that example code you just need to move the save stuff inside the `main` function.

---

<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:** [January 31, 2023, 5:34pm UTC](https://forums.creativeclouddeveloper.com/t/save-multiple-documents-in-subfolder/5776/9 "2023-01-31T17:34:17Z")

</div>

But to expand on what’s happening there;  
When we define a variable in JS we can provide a function call as the value so that the function can execute first and _it’s return value_ becomes the variable’s value.  
Consider that this

```auto
const foo = "bar"

```

is the same as

```auto
function getBar() = {
   return "bar"
}

const foo = getBar()

```

or even as an inline anonymous function

```auto
const foo = () => {
   return "bar"
}

```

As you can already see this is really powerful; especially when you consider that the function logic can be as complex as you like, but it really helps in writing code that is [declarative rather than imperative](https://stackoverflow.com/questions/17826380/what-is-difference-between-functional-and-imperative-programming-languages).  
A good approach to take is that a function should:  
• do one job  
• return a value  
• be agnostic, i.e. it knows nothing about the code that called it or the code it’s returning a value to.

To use our `findOrCreateFolder` as an example, all it knows is that it’s going to be passed a parent folder entry object and a string of the subfolder name to find. It’s either going to find a matching subfolder and return it, or it’s going to create a subfolder and return that. It’s always going to return the named subfolder regardless of whether it existed beforehand, and it works for any parent folder/name combination.

I like to use verbose names for helper functions as it aids readable code. In this entirely fictitious code each helper function returns a value that is assigned to each const and passed into the next function in turn:

```auto
const file = getFileData(path);

const processedFile = processFile(file);

const token = getTokenForProcessedFile(processedFile);

```

I’d also store the code for those helper functions in a separate JS file that I’d import at the top of my code:

```auto
const { getFileData, processFile, getTokenForProcessedFile } = require("path/to/helpers/file")
```

---

<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:** [January 31, 2023, 6:00pm UTC](https://forums.creativeclouddeveloper.com/t/save-multiple-documents-in-subfolder/5776/10 "2023-01-31T18:00:58Z")

</div>

Spoiler - you could do the same for your save functionality…

---

<div class="post-metadata">

**Author:** ![PS-fxrios](https://sea1.discourse-cdn.com/flex015/user_avatar/forums.creativeclouddeveloper.com/ps-fxrios/32/2461_2.png) [@PS-fxrios](https://forums.creativeclouddeveloper.com/u/PS-fxrios)\
**Post date:** [January 31, 2023, 6:02pm UTC](https://forums.creativeclouddeveloper.com/t/save-multiple-documents-in-subfolder/5776/11 "2023-01-31T18:02:21Z")

</div>

@Timothy_Bennett thanks for your teachings!  
While you are still available, I would like to ask you another question:  
If I already have the document open and active and I can get its directory path ( **app.activeDocument.path** ), why do I have to use **fs.getFolder()**; to set the output location of the files?

---

<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:** [January 31, 2023, 6:55pm UTC](https://forums.creativeclouddeveloper.com/t/save-multiple-documents-in-subfolder/5776/12 "2023-01-31T18:55:45Z")

</div>

That’s a design choice by Adobe to protect Marketplace customers from unscrupulous developers who might use full access to your file system for unsavoury practices.

The only real workaround is to have the user select a folder once on initial plugin installation, save that as a persistent token, and then reload it every time the plugin is loaded.  
The issue with this is that you’re expecting users to buy into a set working folder/drive.  
I’ve used this successfully for enterprise plugins, but in that instance every output location is known in advance, not so good if you want dynamic save locations.  
There has been previous talk from Adobe about allowing full access to the filesystem (in particular in regards to comments from enterprise devs), but I have no idea if, and when that might be coming

---

<div class="post-metadata">

**Author:** ![PS-fxrios](https://sea1.discourse-cdn.com/flex015/user_avatar/forums.creativeclouddeveloper.com/ps-fxrios/32/2461_2.png) [@PS-fxrios](https://forums.creativeclouddeveloper.com/u/PS-fxrios)\
**Post date:** [January 31, 2023, 7:13pm UTC](https://forums.creativeclouddeveloper.com/t/save-multiple-documents-in-subfolder/5776/13 "2023-01-31T19:13:12Z")

</div>

Now I understood! The real reason we don’t have full access to the file system is for security reasons, but I already understood how to program this file import and export system using tokens, thanks to your teachings, I think I already feel confident in starting to migrate my CEP mega panel to a UXP plugin. @Timothy_Bennett, thanks again. 🤝 😉

---

<div class="post-metadata">

**Author:** ![Pinus](https://avatars.discourse-cdn.com/v4/letter/p/45deac/32.png) [@Pinus](https://forums.creativeclouddeveloper.com/u/Pinus)\
**Post date:** [February 2, 2023, 12:03pm UTC](https://forums.creativeclouddeveloper.com/t/save-multiple-documents-in-subfolder/5776/14 "2023-02-02T12:03:07Z")

</div>

thank you, really usefull
