One of my colleagues has spent days creating a bunch of files, only to be told that they all need to contain not just the text description, but also the unique code of the item in question. So presently the files are named: Product_Description_A.pdf Product_Description_B.pdf Product_Description_C.pdf etc. The files should actually be called: 001248_Product_Description_A.pdf 003987_Product_Description_B.pdf 1124879_Product_Description_C.pdf etc. At present, we have a folder full of files with the incomplete filename, and a spreadsheet containing the correct filenames. Now I'm great at adding a single prefix/suffix to multiple files, there are a host of programs that will let you do that. What I'm wondering is whether there is any simple way to merge/replace the existing filenames with the unique prefix values using some kind of lookup? I suspect not, but if you don't ask you don't get. We are in a Windows environment, and we are talking about several thousand files. It will be arduous, although I suspect necessary, if we have to manually append each file with the correct prefix.
This can certainly be automated. What I'd do is either copy-and-paste or just export the relevant parts of the spreadsheet into a text file, and write a script (my preference is javascript, but many things could do it) to read that text file, then go through the filenames existing filenames and look up the new modified filename. If you don't have anyone on hand who can do that, throw me a private message including (a small example of) the spreadsheet and some of the files. P
In Linux it would be http://askubuntu.com/questions/438573/how-to-batch-rename-files-images-based-on-csv-file For Windows something like http://stackoverflow.com/questions/5183853/batch-to-find-file-copy-file-then-rename-file-from-a-csv maybe ?
Okay, so yer on Windows and the advice I'm going to give you is for *NIX - but you should be able to do it on Windows by installing Cygwin. Assuming that you can install Cygwin and get a *NIX-like shell up, my advice would be the following: get your list of real filenames in a text file, one per line, called "realnames.txt." Then it's a one-liner: ls *pdf | xargs -I {} sh -c 'mv {} `grep {} realnames.txt`' That finds all pdf files (WARNING: case-sensitive on Linux, probably not case-sensitive on Cygwin) then executes a shell for each PDF that searches for the filename in your list and then moves it (mv) to the correct name. If it doesn't find a match, you'll get an error (because mv will have been called with only one of the two required filenames.) Dun! You could also do it with a "for i in *pdf" loop, but as you've got thousands xargs is the way to go as you won't suddenly run out of resources halfway through the job. EDIT: Proof that it works:
Very sexy responses folks, and super appreciated. I'll have a pop at this tomorrow and let y'all know how it turns out! Muchas gracias!
I do love this forum. It's great! What I would highly recommend not doing is typing: Code: chmod * 444 It made everything go very wrong, and earned me the moniker of 'The CHMOD Kid...'
IIRC it is doable with powershell, but [again iirc since it's a while since I've had to do anything like that] it's a bit of a mare. I'd probably go with Gareth's method with cygwin [also he's gone through the effort of demonstrating it working...], as for cygwin and case sensitivity I don't think it is by default... but i haven't used it in a while so don;t hold me to that...
Cygwin is going to make it rather complicated. I'd do it in jscript, which is already there and working.
If you have a single sheet that contains the correct file names in order you could simply output the list to a suitably formatted text file then use a tool like Bulk Rename Utility that can batch rename files from a list in a text file.
When I was into reading manga more I would download chapters that were named differently. I remember using batch renamers that were both free and useful. Perhaps that would help.
I look forward to your sharing your JavaScript file renaming code. We can compare its complexity relative to my single-line shell command - that should be interesting!
Gareth, your command executed flawlessly. Aside from a few manual fixes I had to make to the source data where symbols had been used in the file names, but that's to be expected with these things. You are a lifesaver!
Late to the party, but here's the PowerShell for the task... it's not quite as short as Gareth's code but is native to Windows. With "FileList.csv" containing old and new file names like so: Code: OldName,NewName Product_Description_A.pdf,001248_Product_Description_A.pdf Product_Description_B.pdf,003987_Product_Description_B.pdf Product_Description_C.pdf,1124879_Product_Description_C.pdf And the expanded easy to read code :
Interesting to see the differences betwix the two methods! For completeness, here's the *NIX shell equivalent to your PowerShell, and which does exactly the same thing: takes a CSV (realnames.csv) as input where the first field is the incorrect filename and the second field is the correct filename and renames the files accordingly: Code: xargs -I {} sh -c 'mv `echo {} | sed "s/,/\ /"`' < realnames.csv For those playing along at home: xargs lets you run commands multiple times from an input list; -I {} tells xargs to assign each line of its input (our CSV) to the variable named {} for use later in the command; sh -c says that for each line xargs should run a shell (sh) with the command that follows in single-quotes; mv is the first half of the move command; `echo {} | sed "s/,\ /"` runs the command located in the backticks, which pushes each line of the CSV through sed to replace the comma with a space; the final single-quote ends the command, which has at this point become mv wrongname.pdf rightname.pdf. < realnames.csv pushes the contents of realnames.csv through xargs as its input. Xargs will then run through the CSV a line at a time, renaming everything as it goes. You could significantly simplify this by using a space as the delimiter when exporting the CSV data, or by processing the CSV file first: Code: cat realnames.csv | sed 's/,/\ /' > realnames.txt Would pre-process the file, swapping all the commas for spaces and outputting it as a new file called realnames.txt, and then the renaming command would simply be: Code: xargs -n2 mv < realnames.txt Isn't scripting fun?
It does slightly more than that... It imports the CSV into a new blank array ($FileList) using the OldName field as key (thus [] brackets): Then goes through each pdf file and renames only those that match an entry in the array. If I'm reading your code correctly (with my limited knowledge): Code: xargs -I {} sh -c 'mv `echo {} | sed "s/,/\ /"`' < realnames.csv I think the PS equivalent would be much simpler: Code: ipcsv ".\FileList.csv" | % {rni ".\$_.OldName" $_.NewName} As it reads the csv natively and doesn't need to spawn a new shell for each action. It just deals with each rename sequentially within the single pipeline. The simple code would raise an exception if there was not a file for each csv line entry (but would continue) which is why I prefer using an array lookup as it doesn't try the command if it doesn't match.
Yeah, my version would display an error but continue in the same vein; your array-based version is undeniably neater from an execution perspective.