2018-12-17T11:47:21Z

WSH(JScript)用ファイルライブラリ:FileUtility.js

WSH(JScript)用ファイル操作関連ライブラリです。
機能概要は、以下の通りです。

  • ファイル/フォルダの作成
  • ファイルの読み込み/書き込み
  • ファイル/フォルダの検索
  • ファイル/フォルダのコピー/移動/削除

サンプル

<?xml version="1.0" encoding="UTF-16" standalone="yes" ?>
<package>
  <job id="main">
    <?job error="false" debug="false" ?>
    <script language="JavaScript" src="FileUtility.js"/>
    <script language="JavaScript"><![CDATA[
(function() {
  "use strict";
  
  function main() {
    // フォルダ直下のファイルのフルパスを表示する
    FileUtility.findFile(function(fullpath) {
      WScript.Echo(fullpath);
    }, '.');
  }
  
  main();
})();
    ]]></script>
  </job>
</package>

参考リンク

FileUtility.js

/*!
 * FileUtility.js v14
 *
 * Copyright (c) 2018 toshi
 * Released under the MIT license.
 * see https://opensource.org/licenses/MIT
 */

/**
 * WSH(JScript)用ファイル関連ライブラリ
 * @requires    module:ActiveXObject('Scripting.FileSystemObject')
 * @requires    module:ActiveXObject('WScript.Shell')
 * @requires    module:ActiveXObject('ADODB.Stream')
 * @requires    module:JSON
 * @requires    module:WScript
 * @auther      toshi(https://www.bugbugnow.net/)
 * @license     MIT License
 * @version     14
 * @see         1 - add - 初版
 * @see         2 - update - Move関数のMoveFile第3引数を削除 - 動作しなかったため
 * @see         3 - update - PrivateUnderscore.jsを導入 - ソフトに共通処理化するため
 * @see         4 - update - find関数関連を修正 - 単純化のため
 * @see         5 - fix - getUniqFilePath()修正 - 拡張子あり時ファイルパスでなくファイル名を返していた
 * @see         6 - update - fs, shをクラス内部確保に変更
 * @see         7 - fix - パス長が規定値を超えた場合、エラーする
 * @see         8 - fix - UTF-8(BOMあり)の3文字未満ファイルをBOMを付けたまま読込んでいた
 * @see         8 - fix - UTF-16BE(BOMなし)の文字なしテキストを読込むとハングする
 * @see         8 - update - UTF-16BEのBOM付き読み書きに対応
 * @see         9 - update - awaitDelete関数を追加
 * @see         9 - update - リファクタリング
 * @see         10 - fix - 移動先ファイルを削除直後の場合、Move関数が動作しない可能性がある
 * @see         10 - update - awaitDelete関数を削除 - 無意味だと判明したため
 * @see         11 - update - リファクタリング
 * @see         12 - update - Move関数のエラー時に待機時間を確保する
 * @see         12 - fix - パス長が規定値を超えた場合、エラーする
 * @see         13 - fix - ファイルあり時、上書きなしでエラーする
 * @see         14 - update - リファクタリング
 */
(function(root, factory) {
  if (!root.FileUtility) {
    root.FileUtility = factory();
  }
})(this, function() {
  "use strict";
  
  var global = Function('return this')();
  var fs = new ActiveXObject('Scripting.FileSystemObject');
  var sh = void 0;
  var _this = void 0;
  
  /**
   * PrivateUnderscore.js
   * @version   5
   */
  {
    try {
      sh = new ActiveXObject('WScript.Shell');
    } catch (e) {}
    function _FileUtility_createFolder(folderpath) {
      var ret = false,
          fullpath = fs.GetAbsolutePathName(folderpath);
      if (!(fs.FolderExists(fullpath) || fs.FileExists(fullpath))) {
        var parentpath = fs.GetParentFolderName(fullpath);
        if (parentpath != '') {
          _FileUtility_createFolder(fs.GetParentFolderName(fullpath));
        }
        try {
          fs.CreateFolder(fullpath);
          ret = true;
        } catch (e) {
          // ファイルが見つかりません(パス長問題) || パスが見つかりません(パス不正 || 存在しない)
        }
      }
      return ret;
    };
    function _FileUtility_createFileFolder(filepath) {
      var ret = false;
      var fullpath  = fs.GetAbsolutePathName(filepath);
      var parentpath= fs.GetParentFolderName(fullpath);
      if (parentpath != '') {
        ret = _FileUtility_createFolder(parentpath);
      }
      return ret;
    };
  }
  
  /**
   * コンストラクタ
   * @constructor
   */
  _this = function FileUtility_constructor() {};
  
  // ADODB関連定義
  _this.AUTODETECT= '_autodetect_all';  // 文字コード自動検出
  _this.ASCII     = 'us-ascii';
  _this.EUC_JP    = 'euc-jp';
  _this.SHIFT_JIS = 'shift-jis';
  _this.UTF_8     = 'utf-8';
  _this.UTF_16    = 'utf-16';           // UTF-16LE
  _this.UTF_16LE  = 'utf-16le';         // UTF-16LE
  _this.UTF_16BE  = 'utf-16be';         // UTF-16BE
  _this.StreamTypeEnum = {
    adTypeBinary: 1,    // バイナリデータ
    adTypeText:   2     // テキストデータ(既定)
  };
  _this.ConnectModeEnum = {
    adModeUnknown:        0,    // 設定が不明であることを表します。(既定)
    adModeRead:           1,    // 読み取り専用の権限
    adModeWrite:          2,    // 書き込み専用の権
    adModeReadWrite:      3,    // 読み取り/書き込み両方の権限
    adModeShareDenyRead:  4,    // 読み取り権限による他ユーザー禁止
    adModeShareDenyWrite: 8,    // 書き込み権限による他ユーザー禁止
    adModeShareExclusive: 12,   // ほかのユーザーの接続を禁止します
    adModeShareDenyNone:  16    // 他のユーザーにも読み取り/書き込みの許可
  };
  _this.StreamReadEnum = {
    adReadAll:    -1,   // ストリームからすべてのバイトを読取(既定)
    adReadLine:   -2    // ストリームから次の行を読み取り
  };
  _this.StreamWriteEnum = {
    adWriteChar:  0,    // テキスト文字列を書き込みます。(既定)
    adWriteLine:  1     // テキスト文字列と行区切り文字書き込み
  };
  _this.SaveOptionsEnum = {
    adSaveCreateNotExist:   1,  // ファイルない時、新しいファイル作成(既定)
    adSaveCreateOverWrite:  2   // ファイルある時、ファイルが上書き
  }
  _this.LineSeparatorsEnum = {
    adCRLF: -1, // 改行文字: CRLF(既定)
    adLF:   10, // 改行文字: LF
    adCR:   13  // 改行文字: CR
  };
  
  // FileSystemObject関連定義
  _this.OpenTextFileIomode = {
    ForReading:   1,    // ファイルを読み取り専用として開きます
    ForWriting:   2,    // ファイルを書き込み専用として開きます
    ForAppending: 8     // ファイルを開き、ファイルの最後に追加
  };
  _this.FileAttributes = {
    Normal:     0,      // 標準ファイル
    ReadOnly:   1,      // 読み取り専用ファイル
    Hidden:     2,      // 隠しファイル
    System:     4,      // システム・ファイル
    Volume:     8,      // ディスクドライブ・ボリューム・ラベル
    Directory:  16,     // フォルダ/ディレクトリ
    Archive:    32,     // 前回のバックアップ以降に変更されていれば1
    Alias:      64,     // リンク/ショートカット
    Compressed: 128     // 圧縮ファイル
  };
  
  // FileUtility_find関数用の定義
  // order(検索順序)
  var folderorder = 0x01; // フォルダを調べる
  var fileorder   = 0x02; // ファイルを調べる
  var suborder    = 0x03; // サブフォルダを調べる
  // 前方検索
  _this.orderFront= (folderorder <<  0) | (fileorder <<  8) | (suborder << 16);
  // 後方検索
  _this.orderPost = (folderorder <<  8) | (fileorder << 16) | (suborder <<  0);
  
  // target(検索対象)
  var subfolder   = 0x01; // サブフォルダを調べる
  var filelist    = 0x02; // ファイルを調べる
  var folderlist  = 0x04; // フォルダを調べる
  var rootfolder  = 0x08; // ルートフォルダを調べる
  var branchfolder= 0x10; // 中間フォルダを調べる
  var leaffolder  = 0x20; // 末端フォルダを調べる
  // 直下ファイル
  _this.targetFiles           =           filelist;
  // サブフォルダ含む全ファイル
  _this.targetAllFiles        = subfolder|filelist;
  // 直下フォルダ
  _this.targetFolders         =                    folderlist|           branchfolder;
  // 末端フォルダ
  _this.targetLeafFolders     = subfolder|         folderlist|                        leaffolder;
  // ルート以外全フォルダ
  _this.targetSubFolders      = subfolder|         folderlist|           branchfolder;
  // ルート含む全フォルダ
  _this.targetAllFolders      = subfolder|         folderlist|rootfolder|branchfolder;
  
  /**
   * フォルダパスからフォルダを作成する
   * @param {string} folderpath - フォルダパス
   * @return {boolean} フォルダ作成有無
   */
  _this.createFolder = function FileUtility_createFolder(folderpath) {
    return _FileUtility_createFolder(folderpath);
  };
  
  /**
   * ファイルパスからフォルダを作成する
   * @param {string} filepath - ファイルパス
   * @return {boolean} フォルダ作成有無
   */
  _this.createFileFolder = function FileUtility_createFileFolder(filepath) {
    return _FileUtility_createFileFolder(filepath);
  };
  
  /**
   * 空ファイルを作成する
   * 既に存在する場合、何もしない。
   * @param {string} filepath - ファイルパス
   * @return {boolean} ファイル作成有無
   */
  _this.createFile = function FileUtility_createFile(filepath) {
    var ret = false;
    if (!_this.Exists(filepath)) {
      _this.storeText('', filepath, false, _this.ASCII);
      ret = true;
    }
    return ret;
  };
  
  /**
   * 空のフォルダを判定する
   * @param {string} folderpath - フォルダパス
   * @return {boolean} 成否
   */
  _this.isEmptyFolder = function FileUtility_isEmptyFolder(folderpath) {
    var ret = false,
        folder,
        fullpath = fs.GetAbsolutePathName(folderpath);
    if (fs.FolderExists(fullpath)) {
      folder = fs.GetFolder(fullpath);
      // ファイルなし && フォルダなし
      try {
        ret = folder.Files.Count == 0 && folder.SubFolders.Count == 0;
      } catch (e) {
        // パス長問題の場合、falseを返す
      }
    }
    return ret;
  };
  
  /**
   * 存在しないファイルパスを返す
   * @param {string} [opt_folderpath=sh.CurrentDirectory] - フォルダパス
   * @param {string} [opt_ext=''] - 拡張子
   * @return {string} 存在しないファイルパス
   */
  _this.getTempFilePath = function FileUtility_getTempFilePath(opt_folderpath, opt_ext) {
    var folderpath = (opt_folderpath != null)?
            fs.GetAbsolutePathName(opt_folderpath):
            sh.CurrentDirectory;
    var ext = (opt_ext && opt_ext.length!=0)? '.'+opt_ext: '';
    
    // 存在しないファイル名を返す
    var fullpath = '';
    do {
      fullpath = fs.BuildPath(folderpath, fs.GetTempName()+ext);
    } while (fs.FileExists(fullpath) || fs.FolderExists(fullpath));
    return fullpath;
    // 補足:fs.GetTempName()関数は、単純にランダムな文字列を返すだけで、
    //      存在有無を意識しないため、存在するかの判定をする。(未確認)
  };
  // 存在しないファイル名称を返す
  _this.getTempFileName = function FileUtility_getTempFileName(opt_folderpath, opt_ext) {
    return fs.GetFileName(_this.getTempFilePath(opt_folderpath, opt_ext));
  };
  
  /**
   * ユニークなファイルパスを返す
   * ファイル名を維持しつつ、末尾に数値を付加したユニークなファイルパスを返す。
   * @param {string} filepath - ファイルパス
   * @return {string} ユニークなファイルパス
   */
  _this.getUniqFilePath = function FileUtility_getUniqFilePath(filepath) {
    var fullpath = fs.GetAbsolutePathName(filepath);
    var folderpath = fs.GetParentFolderName(fullpath);
    var uniqpath = fullpath;
    
    if (fs.FileExists(fullpath) || fs.FolderExists(fullpath)) {
      var ext = fs.GetExtensionName(fullpath);
      if (ext.length !== 0) {
        ext = '.'+ext;
        fullpath = fs.BuildPath(folderpath, fs.GetBaseName(fullpath));
      }
      
      var idx = 1;
      do {
        idx++;
        uniqpath = fullpath + '_'+idx + ext;
      } while (fs.FileExists(uniqpath) || fs.FolderExists(uniqpath));
    }
    return uniqpath;
  };
  // ユニークなファイル名称を返す
  _this.getUniqFileName = function FileUtility_getUniqFileName(path) {
    return fs.GetFileName(_this.getUniqFilePath(path));
  };
  
  /**
   * 有効なファイル名を返す
   * 無効な文字を削除する。
   * @param {string} name - ファイル名
   * @return {string} 有効なファイル名
   */
  _this.getValidFileName = function FileUtility_getValidFileName(name) {
    var marks = ['\\','/',':','*','?','"','<','>','|'];
    for (var i=0; i

変更履歴

更新日 内容
2018/01/17 [v1][add] 初版
2018/02/26 [v1][update] polyfillを追加
2018/02/26 [v2][update] Move関数のMoveFile第3引数を削除
2018/03/24 [v3][update] PrivateUnderscore.jsを導入
2018/03/29 [v4][update] find関数関連を修正
2018/04/08 [v5][fix] getUniqFilePath()を修正
拡張子がある場合、ファイルパスではなくファイル名を返していた
2018/05/04 [v6][update] fs, shをクラス内部確保に変更
2018/05/07 [v6][comment] 著作権表示を追加
2018/05/27 [v7][fix] パス長が規定値を超えた場合、エラーする
2018/06/09 [v8][fix] UTF-8(BOMあり)の3文字未満ファイルをBOMを付けたまま読込んでいた
2018/06/09 [v8][fix] UTF-16BE(BOMなし)の文字なしテキストを読込むとハングする
2018/06/09 [v8][update] UTF-16BEのBOM付き読み書きに対応
2018/06/09 [v9][update] awaitDelete関数を追加
2018/06/09 [v9][update] リファクタリング
2018/06/11 [v10][fix] 移動先ファイルを削除直後の場合、Move関数が動作しない可能性がある
2018/06/11 [v10][update] awaitDelete関数を削除 - 無意味だと判明したため
2018/07/17 [v11][update] リファクタリング
2018/07/24 [v12][update] Move関数のエラー時に待機時間を確保する
2018/07/24 [v12][fix] パス長が規定値を超えた場合、エラーする
2018/12/06 [v13][fix] ファイルあり時、上書きなしでエラーする
2018/12/17 [v14][update] リファクタリング
 コメントを書く