ファイル操作

【Node.js】 ファイルの更新日を現在日時に変更する

更新日:2021/10/22

FTPなどで全てのファイルをサーバーにアップロードしたいときなど、ファイルの更新日時を一括で変更できると便利な場面が時々あります。
Linuxはtouchというコマンド簡単に行えますが、Windowsにはありません。

そこでNode.jsでファイルの更新時刻を変更する方法を調べてみました。

 

更新日時を変更する方法

File systemモジュールのutimesメソッドを使用すると、ファイルの更新時刻とアクセス時刻を変更できます。

utimesの構文

// コールバック版
fs.utimes(path, atime, mtime, callback)

// Promise版
fsPromises.utimes(path, atime, mtime)

utimesの引数

■path:
ファイルのパス

■atime:
変更後の更新時間

Dateオブジェクト、またはUnixエポックタイムをミリ秒で渡します。
具体的には、秒を整数部、それ以下を小数で表した値を使用します。

Dateオブジェクトで指定

const atime =  new Date();

Unixエポックタイムで指定

const atime =  Date.now() / 1000;

■mtime:
変更後のアクセス時間

指定できる値はatimeと同じです。

コールバック版の使用例

コールバック関数はエラーが発生した場合、Errorオブジェクトを引数として受け取ります。

const fs = require("fs");
const t = new Date();

fs.utimes("test.txt",t,t,e=>{
    if( e ) console.log( e.message );
    else console.log( "変更しました" );
});

Promise版の使用例

Promise版のutimesは時刻の更新に成功した場合、結果がundefinedになります。
エラーが発生した場合、Errorオブジェクトがスローされます。

const fs = require("fs/promises");

(async ()=>{
    const t = new Date();
   
    const e = await fs.utimes("test.txt",t,t).catch( e=>e );
    if( e ) console.log( e.message );
    else console.log( "変更しました" );
})();

 

ワイルドカードで変更時刻の一括更新

【Node.js】 ワイルドカードを使用したファイル一覧取得の『自作コードで実装する』で紹介したコードをベースに、一括で変更時刻を更新するコードを作成してみます。

ワイルドカードで変更時刻の一括更新


const fs =  require("fs/promises");
const fpath = require("path");

// エラー終了
const errorEnd = msg => {console.error(msg);process.exit(-1);}

const fileTouch = async (searchPath) => {
    const now = new Date();

    // ①パスをディレクトリとファイル名に分割
    // "/"で終わるならファイル名無しとみなす
    const  {dir,base} = searchPath.endsWith("/") || searchPath.endsWith("\\")
        ? { dir:searchPath , base:null } : fpath.parse( searchPath );

    // ②ファイル名のチェックをおこなう正規表現オブジェクト作成
    const fileMatch = base === null ? null
        : new RegExp("^"
            + base.replace(/(\+)(\(.*?\))|([*?+.{}()\[\]^$|])/g,
                (...s)=> {
                    switch (s[1]===undefined ? s[0] : s[1]){
                        case "+" : return s[2];
                        case "*" : return ".*?";
                        case "?" : return ".";
                        default: return "\\"+s[0];
                    }
                } )
            + "$");

    // ③ディレクトリ内のファイルを取得
    const files = await fs.readdir(dir,{ withFileTypes:true }).catch(e=>({err:e}));
    if( files.err ) errorEnd( files.err.message );

    // ④対象ファイルを抽出
    const result = files.filter( dirent=>{
        // ファイルかどうか
        if( !dirent.isFile() ) return false;
        // 正規表現によるマッチング
        return fileMatch === null ? true
            : fileMatch.test( dirent.name );

    }).map(  // ⑤時刻更新
        dirent =>
            fs.utimes( fpath.join( dir , dirent.name ) , now , now )
                .then(
                    () => ({name:dirent.name})
                    ,e=> ({name:dirent.name,error:e})
                )
    );
    // ⑥時刻更新の結果を待つ
    return await Promise.all( result );

};

この関数を実行すると、Promiseが返ります。
このPromiseはオブジェクトを要素として持つ配列を返します。

オブジェクトの内容は、更新が成功した場合は {name:ファイル名 }、失敗したときは{name:ファイル名 , error:Errorオブジェクト }です。

そのため、次のように結果をthenで受け取ります。

実行例


fileTouch( "c:\\user\\xxxx\\*.txt" )
    .then( result=>
       result.forEach( r=>
           console.log( `${ r.name }:${ r.error ? r.error : "更新しました" }` )
       )
    );

更新日:2021/10/22

書いた人(管理人):けーちゃん

スポンサーリンク

記事の内容について

null

こんにちはけーちゃんです。
説明するのって難しいですね。

「なんか言ってることおかしくない?」
たぶん、こんなご意見あると思います。

裏付けを取りながら記事を作成していますが、僕の勘違いだったり、そもそも情報源の内容が間違えていたりで、正確でないことが多いと思います。
そんなときは、ご意見もらえたら嬉しいです。

掲載コードについては事前に動作確認をしていますが、貼り付け後に体裁を整えるなどをした結果動作しないものになっていることがあります。
生暖かい視線でスルーするか、ご指摘ください。

ご意見、ご指摘はこちら。
https://note.affi-sapo-sv.com/info.php

 

このサイトは、リンクフリーです。大歓迎です。