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

[Extendscript] Best way to move a file via script.

Community Expert ,
Aug 23, 2023 Aug 23, 2023

Copy link to clipboard

Copied

Hi Scripters, does anyone know of the best way to move files via script? For example, here is one method that I got to work, but it has the bad side effect of destroying the file's created/modified dates because it duplicates the file into the desired location, then removes the original. I'm looking for something that works in Illustrator and is cross-platform. Any help would be much appreciated.

- Mark

(function () {

    // WARNING: do not run with an
    // important document open!

    // Example: takes the active document
    // and moves it into a "test" folder
    // created in its current folder
    var doc = app.activeDocument,
        docFile = doc.fullName,
        folder = Folder(docFile.parent.absoluteURI + '/test');

    doc.close(SaveOptions.DONOTSAVECHANGES);
    var movedDocFile = moveFileByCopyDelete(docFile, folder);
    app.open(movedDocFile);

})();

/**
 * Copies a file to a given folder,
 * and removes the original, returning
 * a new reference to the copy.
 * Notes:
 * - This function is a poor workaround
 *   for the lack of a proper MOVE command.
 * - You will lose file metadata such as
 *   created/modified dates.
 * - The original `file` reference will be
 *   invalid after the move, but you can
 *   update it using the returned file.
 * @author m1b
 * @version 2023-08-20
 * @Param {File} file - the file to move.
 * @Param {Folder} folder - the destination folder.
 * @Returns {File} the moved file.
 */
function moveFileByCopyDelete(file, folder) {

    if (!file || !folder)
        return;

    if (file.constructor.name == 'String')
        file = File(file);

    if (folder.constructor.name == 'String')
        folder = Folder(folder);

    if (!folder.exists)
        folder.create();

    if (!file.exists || !folder.exists)
        return;

    var fileCopy = File(folder.absoluteURI + '/' + file.name);
    file.copy(fileCopy);

    if (fileCopy.exists)
        file.remove();

    return fileCopy;

};
TOPICS
Scripting

Views

551

Translate

Translate

Report

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 2 Correct answers

Community Expert , Aug 23, 2023 Aug 23, 2023

Hi, using the OS file system keeps file dates, here's how to do it with vbs, applescript should have something similar. So the idea is to write the below vbs file on the fly with jsx and execute it

 

Set fso = CreateObject("Scripting.FileSystemObject")

f = "C:\files\csaw.txt"
d = "C:\files\temp\csaw.txt"

If FileExists(f) = true Then
  WScript.Echo "Does Exist"
	fso.MoveFile f, d
Else
  WScript.Echo "Does not exist"
End If

Function FileExists(FilePath)
  
  If fso.FileExists(FilePath) Then 
  
...

Votes

Translate

Translate
Community Expert , Aug 23, 2023 Aug 23, 2023

on mac you should be able to do it without applescript, by just using shell scripts instead.

write the shell script commands to a file, then execute the file with File.execute();

youd need to premake a .sh file and give it execute permissions though. but then you can just update the contents of that file dynamically with a script and then execute it.

Votes

Translate

Translate
Adobe
Community Expert ,
Aug 23, 2023 Aug 23, 2023

Copy link to clipboard

Copied

Hi, using the OS file system keeps file dates, here's how to do it with vbs, applescript should have something similar. So the idea is to write the below vbs file on the fly with jsx and execute it

 

Set fso = CreateObject("Scripting.FileSystemObject")

f = "C:\files\csaw.txt"
d = "C:\files\temp\csaw.txt"

If FileExists(f) = true Then
  WScript.Echo "Does Exist"
	fso.MoveFile f, d
Else
  WScript.Echo "Does not exist"
End If

Function FileExists(FilePath)
  
  If fso.FileExists(FilePath) Then 
    FileExists=CBool(1)
  Else
    FileExists=CBool(0)
  End If
End Function

 

Votes

Translate

Translate

Report

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 ,
Aug 23, 2023 Aug 23, 2023

Copy link to clipboard

Copied

on mac you should be able to do it without applescript, by just using shell scripts instead.

write the shell script commands to a file, then execute the file with File.execute();

youd need to premake a .sh file and give it execute permissions though. but then you can just update the contents of that file dynamically with a script and then execute it.

Votes

Translate

Translate

Report

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 ,
Aug 23, 2023 Aug 23, 2023

Copy link to clipboard

Copied

Of course! Thanks heaps @CarlosCanto and @Disposition_Dev. Exactly what I needed. I'll fix that up and post a function when I get the chance. - Mark

Votes

Translate

Translate

Report

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
Engaged ,
Aug 23, 2023 Aug 23, 2023

Copy link to clipboard

Copied

I only had a few minutes to mess with this and it's awefully hacky but it works for Mac and keeps file details intact. You could obviously roll this into one function and check the OS type `var sysOS = /mac/i.test(os) ? "mac" : "win"` to determine the required steps. Hopefully this helps.

 

First you'll need to create a script file, and change the permissions to executable.

$ touch mac_move_file.sh
$ chmod +x mac_move_file.sh

 You'll also need to update the `shellScript` varaible in the JSX file.

(function () {
  // WARNING: do not run with an
  // important document open!

  // Example: takes the active document
  // and moves it into a "test" folder
  // created in its current folder
  var doc = app.activeDocument,
    docFile = doc.fullName,
    folder = Folder(docFile.parent.absoluteURI + "/test");

  var movedDocFile = moveFileByCopyDeleteForMac(docFile, folder);
  $.sleep(2000);
  app.open(movedDocFile);
  alert("File Moved:\n" + movedDocFile);
})();

function moveFileByCopyDeleteForMac(file, folder) {
  shellScript = new File("/Users/jbd/Desktop/mac_move_file.sh");

  if (!file || !folder) return;

  if (file.constructor.name == "String") file = File(file);

  if (folder.constructor.name == "String") folder = Folder(folder);

  if (!folder.exists) folder.create();

  if (!file.exists || !folder.exists) return;

  var fileCopy = File(folder.absoluteURI + "/" + file.name);

  command = "mv " + file + " " + fileCopy;
  writeTextFile(shellScript, command);
  shellScript.execute();

  return fileCopy;
}

function writeTextFile(file, data) {
  try {
    file.encoding = "UTF-8";
    file.open("w");
    file.write(data);
    file.close();
  } catch (e) {
    alert("Error writing file!\n" + e);
  }
}

 

Votes

Translate

Translate

Report

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 ,
Aug 23, 2023 Aug 23, 2023

Copy link to clipboard

Copied

Thanks @jduncan, when I get a chance I'll try it out. I'm especially interested in whether this method is portable in the sense that I can package up the script, along with the executable shell script and give it to someone else and they can run it without problem. I'm wondering if MacOS will revoke executable status when downloaded from the internet by someone else. I might PM to test if you don't mind. Or feel free to do the same if you have a version ready to test.

- Mark

Votes

Translate

Translate

Report

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
Engaged ,
Aug 23, 2023 Aug 23, 2023

Copy link to clipboard

Copied

It's definitely not portable. I just thought maybe you can use the clipboard trick I've seen on here to copy the path to the clipboard and then run a AppleScript file which is portable. I'll work on this idea in a bit and let you know if I can make it work.

Votes

Translate

Translate

Report

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
Engaged ,
Aug 23, 2023 Aug 23, 2023

Copy link to clipboard

Copied

@m1b, I've got a working example using an AppleScript app which should be portable.

 

First, it uses @CarlosCanto's `setClipboard()` function to put the current file path and destination folder on the clipboard. The two paths are separated by a custom delimiter ' ::: ' so the AppleScript can easily split the clipboard string.

 

Next, the the script executes the AppleScript app.

 

Finally, the AppleScript app gets the newly set contents of the clipboard, splits out the path, and moves the Ai file to the destination folder.

 

The AppleScript code is below for reference but it is bundled into an 'app' so I can easily be executed. I have included a Dropbox link below to download the 'app' you would share with your JSX script.

 

App Download Link: https://www.dropbox.com/scl/fo/ba2gggwmol7jxx2zb7lao/h?rlkey=3lvqmgr3hqtu3ommav7br73c1&dl=0

 

One last thing to note, Mac OS X has a lot of security measures, so when the AppleScript is fired for the first time, the users Mac will probably ask them to allow the script to access the folder of the Ai and the destination folder.

 

AppleScript code...

 

# grab the clipboard info
set cb to the clipboard as text

# split the Ai file name from the destination folder using the custom delimeter " ::: "
set arr to split(cb, " ::: ")

# convert the POSIX style paths to an AppleScript file/folder
set fpath to item 1 of arr
set sourceFile to POSIX file fpath
set fpath to item 2 of arr
set destFolder to POSIX file fpath

# move the Ai file
tell application "Finder"
	move sourceFile to destFolder with replacing
end tell

# function to split text on a specified delimiter
to split(someText, delimiter)
	set AppleScript's text item delimiters to delimiter
	set someText to someText's text items
	set AppleScript's text item delimiters to {""}
	return someText
end split

 

 

JSX code...

 

function setClipboard(str) {
  // Hat tip to Carlos Canto on the Adobe Illustrator Forum
  selection = null;
  var idoc = app.activeDocument;
  var tlayer = idoc.layers.add();
  var tframe = tlayer.textFrames.add();
  tframe.name = "TEXT TO COPY";
  tframe.contents = str;
  tframe.translate(10);
  tframe.selected = true;
  app.copy();
  tlayer.remove();
}

var doc = app.activeDocument;
file = File(doc.fullName);
folder = Folder(file.parent.absoluteURI + "/test");
setClipboard(file.fsName + " ::: " + folder.fsName);
applescriptFile = File(Folder.desktop + "/MoveFile.app");
applescriptFile.execute();

 

 

Votes

Translate

Translate

Report

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 ,
Aug 24, 2023 Aug 24, 2023

Copy link to clipboard

Copied

LATEST

Amazing @jduncan! You have saved me a lot of time working out the details here. And Carlos' clipboard trick, nice. Thanks so much. 🙂

- Mark

Votes

Translate

Translate

Report

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