Skip to main content
Inspiring
October 29, 2023
Answered

Recorded action Save as to current folder (instead of a pre-specified folder)?

  • October 29, 2023
  • 3 replies
  • 2757 views

In a recorded action I use a Save as in order to ensure the file is saved with the correct settings. When recording I have been careful to only click on the items I want to be set/adjusted when saving. However, even though I don't click the folder, a specific folder is included in the recorded action. How can I record an action where the file is saved in the current folder, not a pre-specified one? 

 

Correct answer Stephen Marsh

Actions record an absolute, machine/platform specific filename and path.

 

It is possible to only record the absolute file path, without a name if you don't click on or change the name when recording the action:

 

 

You can check the modal control to make the action step interactive, as highlighted below with the red box:

 

 

Otherwise, you would need a script.

 

P.S. There is a hack to record saving the file to a temporary external file path that is then made unavailable (such as a server or removable device), then the path is shown as "file or folder not found" and the action would then default to the current path. Refer to the second last Save step example below:

 

 

3 replies

Stephen Marsh
Community Expert
Community Expert
November 4, 2023

The following script will Save As to the current folder with settings as discussed in this topic:

 

/*
Save As TIFF to Current Folder.jsx
v1.0, 5th November 2023, Stephen Marsh
https://community.adobe.com/t5/photoshop-ecosystem-discussions/recorded-action-save-as-to-current-folder-instead-of-a-pre-specified-folder/td-p/14194382
*/

#target photoshop

    (function () {

        try {
            activeDocument.path;
            var docPath = activeDocument.path.fsName;
            var docName = activeDocument.name.replace(/\.[^\.]+$/, '');
            var saveFileTIFF = new File(docPath + '/' + docName + '.tif');

            /*
            // Interactive confirmation to overwrite an existing file...
            if (saveFileTIFF.exists) {
                // true = 'No' as default active button
                if (!confirm("The file '" + docName + ".tif' exists, overwrite: Yes or No?", true))
                    return;
            }
            */
            
            // Use true to Save As a Copy, false to Save As
            saveTIFF(saveFileTIFF, false);

        } catch (e) {
            alert("Error!" + "\r" + e + ' ' + e.line);
        }

    }());


function saveTIFF(saveFileTIFF, aCopy) {
    tiffSaveOptions = new TiffSaveOptions();
    tiffSaveOptions.embedColorProfile = true;
    // ByteOrder.MACOS or ByteOrder.IBM
    tiffSaveOptions.byteOrder = ByteOrder.IBM;
    tiffSaveOptions.transparency = true;
    tiffSaveOptions.layers = true;
    tiffSaveOptions.layerCompression = LayerCompression.ZIP;
    tiffSaveOptions.interleaveChannels = true;
    tiffSaveOptions.alphaChannels = true;
    tiffSaveOptions.annotations = true;
    tiffSaveOptions.spotColors = true;
    tiffSaveOptions.saveImagePyramid = false;
    // NONE | JPEG | TIFFLZW | TIFFZIP
    tiffSaveOptions.imageCompression = TIFFEncoding.TIFFZIP;
    activeDocument.saveAs(saveFileTIFF, tiffSaveOptions, aCopy, Extension.LOWERCASE);
}

 

There is /* commented out */ placeholder code to confirm overwriting an existing file (the script will overwrite an existing file without interaction unless the disabled code is enabled).

 

https://prepression.blogspot.com/2017/11/downloading-and-installing-adobe-scripts.html

 

dublove
Legend
December 13, 2023

@Stephen Marsh 

Hi~

I was unable to use your script correctly.

Perhaps you can help modify this script to automatically update the path.

 

Now, it is still saved to the recording path.

Please help modify to the directory where the path image is located

-----------------------------------------------------------------

Script name: Repeat the selected action N times

Requirement: You place the action at the front of the panel

-----------------------------------------------------------------

#target photoshop
app.bringToFront();
// Repeat the selected action N times
/////////////////////////////////////////////////////////////////////
// Function: GlobalVariables
// Usage: global action items that are reused
// Input: <none>
// Return: <none>
/////////////////////////////////////////////////////////////////////
function GlobalVariables() {
    gClassActionSet = charIDToTypeID( 'ASet' );
    gClassAction = charIDToTypeID( 'Actn' );
    gKeyName = charIDToTypeID( 'Nm  ' );
    gKeyNumberOfChildren = charIDToTypeID( 'NmbC' );
}
/////////////////////////////////////////////////////////////////////
// Function: GetActionSetInfo
// Usage: walk all the items in the action palette and record the action set
//        names and all the action children
// Input: <none>
// Return: the array of all the ActionData
// Note: This will throw an error during a normal execution. There is a bug
// in Photoshop that makes it impossible to get an acurate count of the number
// of action sets.
/////////////////////////////////////////////////////////////////////
function GetActionSetInfo() {
    var actionSetInfo = new Array();
    var setCounter = 1;
      while ( true ) {
        var ref = new ActionReference();
        ref.putIndex( gClassActionSet, setCounter );
        var desc = undefined;
        try { desc = executeActionGet( ref ); }
        catch( e ) { break; }
        var actionData = new ActionData();
        if ( desc.hasKey( gKeyName ) ) {
            actionData.name = desc.getString( gKeyName );
        }
        var numberChildren = 0;
        if ( desc.hasKey( gKeyNumberOfChildren ) ) {
            numberChildren = desc.getInteger( gKeyNumberOfChildren );
        }
        if ( numberChildren ) {
            actionData.children = GetActionInfo( setCounter, numberChildren );
            actionSetInfo.push( actionData );
        }
        setCounter++;
    }
    return actionSetInfo;
}
/////////////////////////////////////////////////////////////////////
// Function: GetActionInfo
// Usage: used when walking through all the actions in the action set
// Input: action set index, number of actions in this action set
// Return: true or false, true if file or folder is to be displayed
/////////////////////////////////////////////////////////////////////
function GetActionInfo( setIndex, numChildren ) {
    var actionInfo = new Array();
    for ( var i = 1; i <= numChildren; i++ ) {
        var ref = new ActionReference();
        ref.putIndex( gClassAction, i );
        ref.putIndex( gClassActionSet, setIndex );
        var desc = undefined;
        desc = executeActionGet( ref );
        var actionData = new ActionData();
        if ( desc.hasKey( gKeyName ) ) {
            actionData.name = desc.getString( gKeyName );
        }
        var numberChildren = 0;
        if ( desc.hasKey( gKeyNumberOfChildren ) ) {
            numberChildren = desc.getInteger( gKeyNumberOfChildren );
        }
        actionInfo.push( actionData );
    }
    return actionInfo;
}
/////////////////////////////////////////////////////////////////////
// Function: ActionData
// Usage: this could be an action set or an action
// Input: <none>
// Return: a new Object of ActionData
/////////////////////////////////////////////////////////////////////
function ActionData() {
    this.name = "";
    this.children = undefined;
    this.toString = function () {
        var strTemp = this.name;
        if ( undefined != this.children ) {
            for ( var i = 0; i < this.children.length; i++ ) {
                strTemp += " " + this.children[i].toString();
            }
        }
        return strTemp;
    }
}
//////////
function CreateSnapshot(name) {
   function cTID(s) { return app.charIDToTypeID(s); };
    var desc = new ActionDescriptor();
    var ref = new ActionReference();
        ref.putClass( cTID('SnpS') );
    desc.putReference( cTID('null'), ref );
        var ref1 = new ActionReference();
        ref1.putProperty( cTID('HstS'), cTID('CrnH') );
    desc.putReference( cTID('From'), ref1 );
    desc.putString( cTID('Nm  '), name);
    desc.putEnumerated( cTID('Usng'), cTID('HstS'), cTID('FllD') );
    executeAction( cTID('Mk  '), desc, DialogModes.NO );
}
//////////
res ="dialog { \
text:'Repeat the selected action',\
        group: Group{orientation: 'column',alignChildren:'left',\
                corrdination: Panel { orientation: 'row', \
                        text: 'Select Action', \
                                cla: Group { orientation: 'row', \
                                        d: DropDownList {  alignment:'left' },\
                                        }\
                                act: Group { orientation: 'row', \
                                        d: DropDownList {  alignment:'left' },\
                                        }\
                                },  \
                num: Group { orientation: 'row', \
                                    s: StaticText { text:'Execution count:' }, \
                                    e: EditText { preferredSize: [50, 20] } ,\
                                    }, \
                Snapshot:Group{ orientation: 'row', \
                                    c: Checkbox { preferredSize: [16, 16]} ,\
                                    s: StaticText {text:'Create a snapshot (select appropriate actions based on their content)'},\
                                    }, \
                },\
        buttons: Group { orientation: 'row', alignment: 'right',\
                Btnok: Button { text:'determine', properties:{name:'ok'} }, \
                Btncancel: Button { text:'cancellation', properties:{name:'cancel'} } \
                } \
}";
    
win = new Window (res);
    
    GlobalVariables();
    var actionInfo = GetActionSetInfo();
    var ddSet=win.group.corrdination.cla.d;
    var ddAction=win.group.corrdination.act.d;
    if ( actionInfo.length > 0 ) {
        for ( var i = 0; i < actionInfo.length; i++ ) {
            ddSet.add( "item", actionInfo[i].name );
        }
        ddSet.items[0].selected = true;
        ddSet.onChange = function() { 
            ddAction.removeAll();
            for ( var i = 0; i < actionInfo[ this.selection.index ].children.length; i++ ) {
                ddAction.add( "item", actionInfo[ this.selection.index ].children[ i ].name );
            }
            if ( ddAction.items.length > 0 ) {
                ddAction.items[0].selected = true;
            }
            ddSet.helpTip = ddSet.items[ ddSet.selection.index ].toString();
        }
        ddSet.onChange();
    } else {
        ddSet.enabled = false;
        ddAction.enabled = false;
    }
    
    ddAction.onChange = function() {
        ddAction.helpTip = ddAction.items[ ddAction.selection.index ].toString();
    }
    
win.buttons.Btncancel.onClick = function () {
this.parent.parent.close();
}
win.buttons.Btnok.onClick = function () {
   g=Number(win.group.num.e.text);
    g=200;
    if(g<1){
        alert ('-_-!!! You need to run it at least once, right?')
        win.group.num.e.text='1';
        g=1
    }else {
        var b=win.group.Snapshot.c.value;        
        if(b && app.documents.length) {CreateSnapshot(g+"Before executing the action");} //For safety reasons, establish a snapshot
        for(i=0;i<g;i++){
        doAction(ddAction.selection,ddSet.selection) //Execute the selected action
        }
        this.parent.parent.close();
    }
}
win.center();
win.show();

 

Stephen Marsh
Community Expert
Community Expert
December 13, 2023

@dublove 

 

I’m confused...

 

1) Are you referring to my "Save As TIFF to Current Folder.jsx" script? If so, what problem did you have?

 

2A) That code isn’t my script (Repeat Action N Times)

 

2B) It has no saving code in it, all it does is repeat an action a set number of times

 

Please keep your replies in your original topic.

 

Stephen Marsh
Community Expert
Community Expert
November 2, 2023

@Chris201Chris 

 

So how did the updated action go?

 

Inspiring
November 4, 2023

😂 I'm not having much luck I'm afraid. This action opens up the save as window and "waits"... so it is the same as if I instead of starting the action just press Shift+Ctrl+S...

(I don't know if there are any more methods to try, but if there is, and you are willing to try again, could you please add the alternative "Image compression: zip" as well - I know I did't have it in my original action, but am trying to compress my files when possible)

Stephen Marsh
Community Expert
Community Expert
November 4, 2023

But it DID open to the current image location, yes???  :]

 

I believe that you have now exhausted the possibilities of Actions if you don't wish to have interactivity. 

A script can silently save into the current directory without a dialog.

 

The script save step can be recorded into an Action.

Stephen Marsh
Community Expert
Stephen MarshCommunity ExpertCorrect answer
Community Expert
October 29, 2023

Actions record an absolute, machine/platform specific filename and path.

 

It is possible to only record the absolute file path, without a name if you don't click on or change the name when recording the action:

 

 

You can check the modal control to make the action step interactive, as highlighted below with the red box:

 

 

Otherwise, you would need a script.

 

P.S. There is a hack to record saving the file to a temporary external file path that is then made unavailable (such as a server or removable device), then the path is shown as "file or folder not found" and the action would then default to the current path. Refer to the second last Save step example below:

 

 

Inspiring
October 29, 2023

Thanks!

The first suggestion doesn't work for me as the problem is not that a new file name is added, but that, even if I do not click or change the name when recording the action - the path is saved and thus "fixed".

Neither does the second suggestion work as I want the rest of the "save as" step to work, it is just the part of the folder selection I do not want and that is not a separate step and thus does not seem to be able to turn off with the modal control.

The third suggestion, the "hack" should probably do the trick  - I haven't tried it yet, but the way it sounds it should work.
Again, many thanks!