Search code examples
javascriptnode.jsbatch-rename

batch script to rename '.txt' files, by using 'date' found within file


I am starting with this logic:

const fs = require("fs")

// Read directory
fs.readdir("./", (err, files) => {

  for (const file of files) {

    if (/[A-Z]/g.test(file)) {

      fs.rename(file, 'newFile.txt', (err) => {
        console.log('Renaming', file, "to", "newFile.txt")
        if (err) throw err
      })
    }
  }
})

I essentially want to iterate through a directory that has a couple dozen .txt files within it. I want to search for a date found within each .txt file and USE THAT as the new name of the file.

For instance within each text file, this is found within it (a date in this format) 2015-12-21

I would like to iterate through the directory of .txt files, search and find a date in this format (XXXX-XX-XX), then use it as the new name for the file.


I am thinking this could be the regex for finding the date:

([12]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]))

Below is an example of text file content, it has multiple content like the below: You'll notice the date to the right there, there are multiple dates listed like that, but they are all the same; so I just need to grab it and use it as the updated file name.

PRIORITY GOAL                                                                IN_PROGRESS_SINCE SOURCE  TYPE
-------- ------------------------------------------------------------------- ----------------- ------- --------------------
4        Has received blahblahblah on improving physical activity              2015-12-21 15:51  MEMBER  NULL

          BARRIER              SENSITIVE STATUS   NOTE
---- ---- -------------------- --------- -------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
          Needs counseling on  No        Not Met  

Solution

  • You could use regex expressions to search for a date:

    // dir is the directory containing the file
    // Specify utf8 as encoding to get a string
    let fileContents = fs.readFileSync(path.join(dir, /*fs.Dirent*/file.name), 'utf8')
    let dateMatches = fileContents.match(/[12]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])/)
    

    If there is a date, dateMatches will be an array with length greater than zero. The first element will contain the first date encountered in the file contents.

    const fs = require('fs')
    const path = require('path')
    
    // Change ./example to whatever you like
    let dir = './example'
    
    fs.readdir(dir, {
      encoding: 'utf8',
      withFileTypes: true
    }, (err, files) => {
      if (err) {
        // Error happened when reading the directory
        console.error(err)
        return
      }
      for (const file of files) {
        if (!file.isFile()) {
          // Directory or block device?
          continue;
        }
    
        // Read file contents
        let fileContents = fs.readFileSync(path.join(dir, file.name), 'utf8')
        let dateMatches = fileContents.match(/[12]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])/)
        if (dateMatches) {
          // There is a date here
          fs.rename(path.join(dir, file.name), path.join(dir, dateMatches[0]), (err) => {
            if (err) {
              console.error(err)
              // Do your error handling stuff here...
    
              return
            } else {
              console.log('Renamed', file.name, 'to', dateMatches[0])
            }
          })
        }
      }
    })
    

    Note that the file may contain invalid dates, such as 2018-02-30. If that's an issue for you, you can validate the date with Date.parse or use a library such as Moment.js.

    You might want to check the Node.js documentation for details.


    For example, if ./example/file1.txt would contain the following:

    DATE
    ====
    2019-01-01
    1970-12-31
    

    executing the program above would rename it to ./example/2019-01-01.