How to rename a large number of files using Java
Use case
Imagine you have about 20 folders and each folder has 50 – 100 pdf documents in it. Pdf file names have similar structure, let’s say year-month-user_id.pdf e.g. 2012-oct-396.pdf. If, for some reason, user_id has changed, perhaps after a db migration, you’ll need to edit the names of all pdf files in order to make them available for download again (let’s suppose our link is generated every time and it depends on the user_id). You can rename all the files manually, but I think it will be faster if you let the computer do it for you.
OK, first thing is to prepare a list of old and new user ID values.
100,13917 101,13918 110,13927 112,13929 114,13931 115,13932 124,13941 126,13943 130,13947 ...
Place this csv file as a resource and convert it to Map<String, String>
. Key will be an old ID and value is new ID.
private Map<String, String> getOldAndNewIds(String fileName) { InputStream is = Renamer.class.getResourceAsStream(fileName); String[] s = new Scanner(is).useDelimiter("\\A").next().split("\n"); Map<String, String> idsMap = new HashMap<String, String>(); for (String id : s) { idsMap.put(id.split(",")[0], id.split(",")[1]); } return idsMap; }
We are passing a file name to this method and getting the resource so we can modify it and put it in our map. You may notice funny name for our class, Renamer
, but let’s not pay too much attention to it. What can be interesting to us in this method is the 6th line. Take a look at the example of our csv file and you’ll see the commas between ID values. We are splitting every row by comma and setting first number as key and second one as a value. That’s how we get our Map we will use later for renaming.
Now, let’s create a main
method
public static void main(String args[]) { File rootFolder = new File(ROOT_FOLDER); File[] folders = rootFolder.listFiles(); Map<String, String> ids = getOldAndNewIds("old_new_users.csv"); for (File folder : folders) { File[] files = folder.listFiles(); for (File file : files) { String fileName = file.getName(); String userId = fileName.split("-")[2].split("\\.")[0]; String newFileName = fileName.split("-")[0] + "-" + fileName.split("-")[1] + "-" + ids.get(userId) + ".pdf"; newFileName = newFileName.replace("\r", ""); File tempFileName = new File(folder, newFileName); file.renameTo(tempFileName); } } }
Let’s explain few lines now:
- Line 2 – This is where we are setting the root folder.
- Line 3 – We are getting all the folders in our root folder
- Line 4 – Here we get our Map of old/new ID values.
- Line 7 – For each folder we get all pdf files.
- Line 10 -We are extracting userId from the file name. Remember the format of the name 2012-oct-396.pdf. As you can see we split the file name twice. First time we split them by the “-” to get the last part (“396.pdf”) and then we split them by “.” to get the “396” (userId)
- Line 11,12 – Creating the new file name. Splitting again to get the “2012-oct-“. After that, you may notice we used our map
ids.get(userId)
to get the new value. Remember, old userId is the key and we are accessing the value in the map by the key. After that, we just appended “.pdf”. - Line 13 – For some reason, our new file name contained the carriage return control character so we had to remove it.
- Line 15 – Giving our file the new file name. On the line 14 we preserve the folder information (where the file is located), so the new file won’t end up in different folder.
Now, if you run our main method, all your files will be renamed immediately. As you may notice this is suitable for very specific situation. I didn’t do any checks because I knew how my files are named and organized. This can be improved, and make more configurable.
AJAX with Spring MVC Import data from CSV files into MySQL