File.strf (aka File name formatting.

Photoshop Script Snippets - Note: Full Scripts go in the Photoshop Scripts Forum

Moderators: Tom, Kukurykus

xbytor

File.strf (aka File name formatting.

Post by xbytor »

Here is one of my favorite bits of code from xtools/xlib/stdlib.js: File.strf(). It's a handy routine for getting the file extension, base file name, etc... and doing interesting things with them usually to create new file names.

Here's the docs:

File.strf(fmt [, fs])
Folder.strf(fmt [, fs])
This is based of the file name formatting facility in exiftool. Part of
the description is copied directly from there. You can find exiftool at:
http://www.sno.phy.queensu.ca/~phil/exiftool/

Description:
Format a file string using a printf-like format string

fmt is a string where the following substitutions occur
%d - the directory name (no trailing /)
%f - the file name without the extension
%e - the file extension without the leading '.'
%p - the name of the parent folder
%% - the '%' character

If fs is true the folder is in local file system format (Windows only)
(e.g. C:\images instead of /c/images)


Examples:

Reformat the file name:
var f = new File("/c/work/test.jpg");
f.strf("%d/%f_%e.txt") == "/c/work/test_jpg.txt"

Change the file extension
f.strf("%d/%f.psd") == "/c/work/test.psd"

Convert to a file name in a subdirectory named after the extension
f.strf("%d/%e/%f.%e") == "/c/work/jpg/test.jpg"

Change the file extension and convert to a file name in a subdirectory named
after the new extension
f.strf("%d/psd/%f.psd") == "/c/work/psd/test.psd"

Handle '.xxx' files
var f = new File("~/.bashrc");
f.strf("%f") == ".bashrc"
f.strf("%e") == ""

Advanced Substitution
A substring of the original file name, directory or extension may be
taken by specifying a string length immediately following the % character.
If the length is negative, the substring is taken from the end. The
substring position (characters to ignore at the start or end of the
string) may be given by a second optional value after a decimal point.
For example:

var f = new File("Picture-123.jpg");

f.strf("%7f.psd") == "Picture.psd"
f.strf("%-.4f.psd") == "Picture.psd"
f.strf("%7f.%-3f") == "Picture.123"
f.strf("Meta%-3.1f.xmp") == "Meta12.xmp"

Note that other format specifiers (like %d and %s) are silently passed through in case you need to process the string with another sprintf-like function.

And here's the code. Careful use of RegExp makes this relatively easy.

Code: Select allFile.prototype.strf = function(fmt, fs) {
  var self = this;
  var name = decodeURI(self.name);
  //var name = (self.name);

  // get the portions of the full path name

  // extension
  var m = name.match(/.+\.([^\.\/]+)$/);
  var e = m ? m[1] : '';

  // basename
  m = name.match(/(.+)\.[^\.\/]+$/);
  var f = m ? m[1] : name;

  fs |= !($.os.match(/windows/i)); // fs only matters on Windows
//  fs |= isMac();

  // full path...
  var d = decodeURI((fs ? self.parent.fsName : self.parent.absoluteURI));

  // parent directory...
  var p = decodeURI(self.parent.name);

  //var d = ((fs ? self.parent.fsName : self.parent.toString()));

  var str = fmt;

  // a regexp for the format specifiers

  var rex = /([^%]*)%(-)?(\d+)?(\.\d+)?(%|d|e|f|p)(.*)/;

  var result = '';

  while (m = rex.exec(str)) {
    var pre = m[1];
    var sig = m[2];
    var len = m[3];
    var ign = m[4];
    var typ = m[5];
    var post = m[6];

    var subst = '';

    if (typ == '%') {
      subst = '%';
    } else {
      var s = '';
      switch (typ) {
        case 'd': s = d; break;
        case 'e': s = e; break;
        case 'f': s = f; break;
        case 'p': s = p; break;
        // default: s = "%" + typ; break; // let others pass through
      }

      var strlen = s.length;

      if (strlen && (len || ign)) {
        ign = (ign ? Number(ign.slice(1)) : 0);
        if (len) {
          len = Number(len);
          if (sig) {
            var _idx = strlen - len - ign;
            subst = s.slice(_idx, _idx+len);
          } else {
            subst = s.slice(ign, ign+len);
          }
        } else {
          if (sig) {
            subst = s.slice(0, strlen-ign);
          } else {
            subst = s.slice(ign);
          }
        }

      } else {
        subst = s;
      }
    }

    result += pre + subst;
    str = post;
  }

  result += str;

  return result;
};
Folder.prototype.strf = File.prototype.strf;


-X