Script: Export selected records as ZIP archive

A hand-crafted JavaScript script that can be

  • installed inside DT (see the manual for instructions)
  • run outside DT in script editor
  • run outside DT with osascript -l JavaScript <scriptfile.js> (without the pointy brackets!).

(Edit: The script does not run from DT’s scripting menu because currently doShellScript() raises an error in this situation. It should, however, be possible to run the script from the global script menu)

It takes the currently selected files in DT, asks the user for an archive file name and stores them in that file as a ZIP archive, removing the internal DT directory information in the process.

So, a file stored in /User/you/databases/myDatabase.dtBase2/Files.noIndex/pdf/8/filename.pdf will appear in the ZIP archive as filename.pdf.

On extracting, that prevents the creation of a useless folder hierarchy.
But it will cause problems if two files with identical names but different locations in DT are saved in the same archive. The zip command will not accept that and bail out.

(() => {
  const app = Application("DEVONthink")
  app.includeStandardAdditions = true;
  
  // Bail out if no records are selected
  if (! app.selectedRecords().length) {
    app.displayAlert('No records selected, abandoning.');
    return;
  }
  // Get paths of all selected records, escape single quotes 
  // and wrap the path in single quotes
  const filePaths = app.selectedRecords.path().map(p => `'${p.replaceAll("'","\\'")}'`);
  
  // Get path to target archive. 
  // toString() is needed because choseFileName doesn't return a string
  let zipFile = app.chooseFileName({withPrompt: 'Archive to create', defaultName: 'Archive',
    defaultLocation: Application('System Events').desktopFolder().posixPath()});
  zipFile = zipFile.toString();
  
  // Append '.zip' if needed
  if (! zipFile.endsWith('.zip')) {
    zipFile += '.zip';
  }
  
  // Built the shell command to create the archive. 
  // The '-j' stores only the filename itself in the archive, without any path information
  const shellCommand = `/usr/bin/zip -j '${zipFile}' ${filePaths.join(" ")}`;
  const curApp = Application.currentApplication();
  curApp.includeStandardAdditions = true;
  
  // Run shell command with error handling
  try {
    curApp.doShellScript(shellCommand);
  } catch (e)  {
    app.displayAlert(e.message, { 
        message: "An error occured", 
        as: "critical",
        button: "OK"
    })  
  }
})()
1 Like