あるディレクトリの中にあるファイルたちの名前をまとめて変更したいなぁ、というときがあり、node.jsでやってみました。
要件
- node.js がインストールされている
- 特定のフォルダ内のファイルを一括リネームしたい
- 対象のファイルを種類(拡張子)で抽出したい(フィルタリングしたい)
例
- ディレクトリ「textBox」内にある「●●●.txt」ファイルをリネームします(他の拡張子は無視)
- リネームの内容:ファイル名の先頭にディレクトリ名を追加します(「ディレクトリ名_ファイル名」にする)
- 実行するjsファイル名は「changeName.js」にしています(任意のものでOK)
手順
1)jsファイルの作成
constfs=require("fs");constpath=require("path");constdir="./textBox";// ← 変更してねconstaddHead="textBox_";// ← 変更してねconstfileNameList=fs.readdirSync(dir);consttargetFileNames=fileNameList.filter(RegExp.prototype.test,/.*\.txt$/);// ← 変更してね// console.log(targetFileNames);targetFileNames.forEach(fileName=>{// console.log(fileName)constfilePath={};constnewName=addHead+fileName;filePath.before=path.join(dir,fileName);filePath.after=path.join(dir,newName);// console.log(filePath);fs.rename(filePath.before,filePath.after,err=>{if(err)throwerr;console.log(filePath.before+"-->"+filePath.after);});});
const dir = "./textBox"
にはchangeName.js
のあるカレントディレクトリからのパスを入力const addHead = "textBox_";
にはファイル名の先頭に付与する文字列を入力const targetFileNames = fileNameList.filter(RegExp.prototype.test, /.*\.txt$/);
の後半部の.txt
で抽出したいファイルの拡張子を指定
2)jsファイルの実行
$node changeName.js
以上です。
解説
constfs=require("fs");// nodeのfsモジュール読み込みconstpath=require("path");// nodeのpathモジュール読み込みconstdir="./textBox";// 対象のディレクトリを指定constaddHead="textBox_";// ファイル名に付与したい文字列を入力constfileNameList=fs.readdirSync(dir);// 対象ディレクトリからファイル名一覧を取得console.log(fileNameList);// [ 'textBox_aaa.txt', 'textBox_bbb.txt', 'textBox_ccc.txt', 'xxx.jpg' ]consttargetFileNames=fileNameList.filter(RegExp.prototype.test,/.*\.txt$/);// ファイル名一覧から、拡張子で抽出console.log(targetFileNames);// [ 'textBox_aaa.txt', 'textBox_bbb.txt', 'textBox_ccc.txt' ]/* 拡張子で抽出したファイル名一覧「targetFileNames」を forEach で回す */targetFileNames.forEach(fileName=>{console.log(fileName);// textBox_aaa.txtconstfilePath={};// ファイル名の前後を入れる箱(連想配列)constnewName=addHead+fileName;// 元のファイル名の先頭に、文字列「addHead」を加えるfilePath.before=path.join(dir,fileName);// 変更前のフルパス(ディレクトリパス+ファイル名)を箱に入れるfilePath.after=path.join(dir,newName);// 変更後のフルパスを箱に入れるconsole.log(filePath);// { before: 'textBox/aaa.txt', after: 'textBox/textBox_aaa.txt' }/* リネーム処理 */fs.rename(filePath.before,filePath.after,err=>{if(err)throwerr;console.log(filePath.before+"-->"+filePath.after);// textBox/aaa.txt-->textBox/textBox_aaa.txt});/* END リネーム処理 */});/* END forEach */
require
本件は、node.jsの組み込みモジュール(標準モジュール)だけで実施可能です。
公式ドキュメント → File System Path
constfs=require("fs");// nodeのfsモジュール読み込みconstpath=require("path");// nodeのpathモジュール読み込み
fs.readdirSync(path)
指定フォルダ(path)内のファイル・サブフォルダ名を取得します(詳細)。
フィルタリングする前なので「xxx.jpg」も含まれています。
constfileNameList=fs.readdirSync(dir);// 対象ディレクトリからファイル名一覧を取得console.log(fileNameList);// [ 'textBox_aaa.txt', 'textBox_bbb.txt', 'textBox_ccc.txt', 'xxx.jpg' ]
Array.filter()
filter() メソッドは、引数として与えられたテスト関数を各配列要素に対して実行し、それに合格したすべての配列要素からなる新しい配列を生成します。(詳細)
ようは、「●●●.txt」だけを抽出するフィルタとして使っています。
もしフィルタが不要でしたら .filter(RegExp.prototype.test, /.*\.txt$/)
を除去すればOKです。
(もしくは forEach()
にはフィルタ前の fileNameList
を渡すようにする)
consttargetFileNames=fileNameList.filter(RegExp.prototype.test,/.*\.txt$/);// ファイル名一覧から、拡張子で抽出console.log(targetFileNames);// [ 'textBox_aaa.txt', 'textBox_bbb.txt', 'textBox_ccc.txt' ]
Array.forEach()
forEach() メソッドは与えられた関数を、配列の各要素に対して一度ずつ実行します。(詳細)
拡張子で抽出したファイル名一覧「targetFileNames」からファイル名を1つずつ取り出して、リネームの処理を実行していきます。
targetFileNames.forEach(fileName=>{console.log(fileName);// textBox_aaa.txt// 〜省略〜});
連想配列にリネーム前後のファイル名を入れる
constfilePath={};constnewName=addHead+fileName;filePath.before=path.join(dir,fileName);filePath.after=path.join(dir,newName);console.log(filePath);// { before: 'textBox/aaa.txt', after: 'textBox/textBox_textBox_aaa.txt' }
filePath
という連想配列の箱を用意して、その中にリネーム前とリネーム後のファイル名を入れています。
リネームするときはフルパス(ディレクトリパス+ファイル名)が必要なので、 path.join
でフルパスにしています(詳細)。
fs.rename(oldPath, newPath, callback)
リネーム処理をする部分です。第一引数に変更前のファイルのフルパス、第二引数には変更後のファイルのフルパスを入れます(詳細)。
fs.rename(filePath.before,filePath.after,err=>{if(err)throwerr;console.log(filePath.before+"-->"+filePath.after);// textBox/aaa.txt-->textBox/textBox_aaa.txt});
あとがき
【注意!】 本件を試す際は、どうかリネーム前にフォルダ(ファイル)のコピーを作成ください。リネーム後に戻すのは大変ですよ!
本件はファイル名の先頭に文字を足すだけでしたが、文字列を検出して置換したり、連番を振ったり...処理を足して色々と応用できると思います。
お役に立てば幸いです。
リスペクトな記事
本件のために参照させていただきました記事です。