Skip to content

Instantly share code, notes, and snippets.

@nenadom
Last active July 22, 2018 20:25
Show Gist options
  • Save nenadom/b284c0688dd8d72b9dd0ad7267d23a8b to your computer and use it in GitHub Desktop.
Save nenadom/b284c0688dd8d72b9dd0ad7267d23a8b to your computer and use it in GitHub Desktop.
Renames a collection of %COUNTRY_NAME%.ext files to a matching set of %ISO_CODE%.ext files.
/**
* Renames a collection of %COUNTRY_NAME%.ext files to a matching set of
* %ISO_CODE%.ext files.
*
* Uses the https://github.com/datasets/country-codes dataset for names
* and ISO codes. Since it's CSV, I also used
* https://github.com/Keyang/node-csvtojson to convert to JSON.
*
* V 0.0.2.
*/
const fs = require('fs')
const Converter = require('csvtojson').Converter
const COUNTRY_DATASET_DIR = './country-codes/data/country-codes.csv'
var converter = new Converter({})
var normalizedCountries = {}
// flatten out JSON data to a name: iso dictionary on parse end
converter.on('end_parsed', function(json) {
normalizeJSONData(json, init)
})
// read CSV data
fs.createReadStream(COUNTRY_DATASET_DIR).pipe(converter)
// provide dir to work on as first arg
var targetDir = process.argv[2]
// provide a second dir as arg, or default to ./processed
var newDir = process.argv[3] || './processed/'
if (!targetDir) {
console.log('give me a valid directory to work on!')
return
}
// validate directories and add slashes at end
if (targetDir[targetDir.length - 1] !== '/') targetDir = targetDir + '/'
if (newDir[targetDir.length - 1] !== '/') newDir = newDir + '/'
/**
* ================
* Main init
* ===============
*/
function init() {
// see if newDir exists and create it if not
fs.stat(newDir, function(err, stats) {
if (stats && stats.isDirectory()) {
batchRename() // Do rename now.
return
}
// otherwise, init rename after creating dir thru callback
fs.mkdir(newDir, function(err) {
if (err) throw err
batchRename() // Or now.
})
})
}
/**
* NOTE: use read/write streams to make copies of existing files,
* fs.rename moves the actual file
*/
function batchRename() {
console.log('renaming...')
fs.readdir(targetDir, function(err, flagFiles) {
if (err) throw err
flagFiles.map(function(flagName) {
var newName
// ignore pesky .DS_Store files
if (flagName == '.DS_Store') return;
// rename file
newName = renameFile(flagName)
// streams, baby
fs.createReadStream(targetDir + flagName)
.pipe(fs.createWriteStream(newDir + newName))
.on('error', console.error)
})
})
console.log('renaming complete!')
}
/**
* Splits filename into name and extension; if name in list of
* normalized countries (a dictionary of names and ISO3166-1 codes),
* return that code, with extension. Otherwise, return filename.
*
* @param {String} filename i.e. ''
* @return {[type]} [description]
*/
function renameFile(filename) {
var strSplit = filename.split('.');
var name = strSplit[0]
var ext = '.' + strSplit[1]
if (normalizedCountries[name]) {
return normalizedCountries[name] + ext
}
return filename
}
/**
* Extracts data from country info relevant to renaming files.
* Init renaming thru callback
*
* @param {Array} json converted CSV data
* @param {Function} callback callback init() function
* @return {undefined}
*/
function normalizeJSONData(json, callback) {
json.map(function(country) {
var name = slugifyName(country['name'])
var iso = country['ISO3166-1-Alpha-2'].toLowerCase()
normalizedCountries[name] = iso;
})
// init
callback()
}
/**
* Slugify name.
*
* @param {String} name Full name with spaces, dots, ampersands, weird letters
* @return {String} slug
*/
function slugifyName(name) {
// yeah this should be done using regexp
return name.split('').map(function(char) {
if (char == ' ') return '_'
if (char == '.') return ''
if (char == '&') return 'and'
if (['Å', 'ã', 'â', 'à', 'á'].indexOf(char) >= 0) return 'a'
if (['Ê', 'è', 'ȇ', 'é'].indexOf(char) >= 0) return 'e'
// at least a little bit of regexp
return char.replace(/[A-Z]/g, function(match) {
return match.toLowerCase()
})
}).join('')
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment