2

I'm not very familiar with windows bat file programming and I would appreciate any help with this.

I need a bat file to do the following:

  • extract folder name from a filename - eg, extract Chemistry from the filename "123-Chemistry-101.rep". "-" can be used to denoted start & end of token.
  • move the same file into a folder called Chemistry. Chemistry will be a sub dir of where all the reports are.

I can probably do the 2nd part of it (which I found on this site) but the first part is beyond my skill.

eg, for /R U:\Test %%f in (*.rep) do copy %%f U:\test\Chemistry\

Regards, Durand

2 Answers2

3

You asked for Batch, but i answer with Powershell because i think that today Batch is a bit obsolete for such a task, hoping your system supports Powershell :

$rootDir = "U:\Test"

$files = Get-ChildItem $rootDir -Filter *.rep

foreach($file in $files) {
  $folder = $file.toString().split("-")[1]
  $sourcefile = "$rootDir\$file"
  $targetdir = "$rootDir\$folder"
  if(!(Test-Path -Path $targetdir )){
    New-Item -ItemType directory -Path $targetdir
  }
  Move-Item $sourcefile $targetdir
}

Edit @Karan :

Recursive (keeping subdir tree) :

$rootDir = "U:\Test"

$files = Get-ChildItem $rootDir -Filter *.rep -Recurse

foreach($file in $files) {
  $sourcefile = $file.Fullname
  $filepath = $file.PSParentPath
  $newfoldertocreate=$file.toString().split("-")[1]
  if(!(Test-Path -Path $filepath\$newfoldertocreate)){
    New-Item -ItemType directory -Path $filepath\$newfoldertocreate
  }
  Move-Item $sourcefile $filepath\$newfoldertocreate
}
user2196728
  • 1,306
  • Batch will never die! :P (BTW my batch code is much shorter than PS in this case at least. It also handles .REP files in sub-folders whereas this code works only for a single level. I tried adding -Recurse to Get-ChildItem but it didn't work properly. Can you suggest how this can be handled?) – Karan May 22 '15 at 03:20
  • @Karan : I know Batch will never die...Here's an edit for recursive as you asked. The trick is to get the full path for files in subdirectories. Then, what about target dir ? Should it have sub-folders ? Assuming "no" here. My script got "too much" lines in order to be make it very clear...However it could be shortened... – user2196728 May 28 '15 at 19:43
  • I tested with sub-folders in the Reports folder (rootDir) and it failed. Just to be clear, rootDir is D:\New folder. I have D:\New folder\123-Chemistry-101.rep, D:\New folder\123-Phys Ed-101.rep, D:\New folder\New folder\123-Chemistry-101.rep and D:\New folder\New folder\123-Phys Ed-101.rep (just 4 files in two levels of folders). – Karan May 28 '15 at 19:53
  • Do i have to understand that you have spaces in folder names and file names ? ;) – user2196728 May 28 '15 at 19:55
  • Yes, clearly. :) (BTW I hope you understand I'm not the one who asked this question, so feel free to ignore these enhancement requests if you don't have the time or inclination. Just that I'm trying to understand how to do this same thing best with PowerShell even though I've already accomplished it with a 3-line batch file.) – Karan May 28 '15 at 19:58
  • I have time! And glad if i can help you going further with Powershell ;) I've tested your case and it works for me. The only caveat is that there are identical filenames. What is the exact error message you got ? – user2196728 May 28 '15 at 20:19
  • Thanks! :) Here's the error. Only the two files in D:\New folder are moved into respective sub-folders, but the files under D:\New folder\New folder aren't touched. – Karan May 28 '15 at 20:34
  • You encounter the caveat i've told about : you have files with same names ! So, the system is telling you that it cannot move the file because another one with the same name already exists in destination folder. D:\New folder\123-Phys Ed-101.rep = D:\New folder\New folder\123-Phys Ed-101.rep How do you want to handle this ? – user2196728 May 28 '15 at 20:38
  • Ah, I get it, your script has only a single destination folder targetdir directly under rootDir. What I want is D:\New folder\Chemistry and D:\New folder\New folder\Chemistry, i.e. at whichever level it finds .REP files, at that level it should create appropriate sub-folders and move the files to them. – Karan May 28 '15 at 20:42
  • @Karan Should work, see my edit. Of course, script very detailed. – user2196728 May 28 '15 at 22:12
  • Script's not general enough to deal with multiple levels. Now it works for 2 but if I have 3 levels, i.e. New folder with 2 REP files, New folder\New folder with another 2 (same names) and New folder\New folder\New folder with another 2 (again same names) it fails again. Forget it, don't want to bother you and waste more of your time on it. I'll work on it later. Thanks a lot! – Karan May 29 '15 at 00:48
  • @Karan I've modified my Edit. This one should work as you expect :) – user2196728 May 29 '15 at 13:05
  • Yes, so far as per my tests I think this one does the job. Excellent, wish I could upvote more than once. Thanks! – Karan May 30 '15 at 00:14
  • @Karan You are welcome. Was simple but was tired ;) After a good night things appear clearly to me :) – user2196728 May 30 '15 at 00:15
2

Run this batch file from the parent folder of Reports folder:

for /f "delims=" %%a in ('dir /b /s "Reports folder\*.rep"') do for /f "tokens=2 delims=-" %%i in ("%%~a") do (
    if not exist "%%~dpa%%i\" md "%%~dpa%%i"
    move "%%~a" "%%~dpa%%i\"
)

%%a and %%i are the variables used in the two for loops.The former contains the full paths to the .REP files (courtesy the outer loop), and the latter contains the folder names extracted from the file names (courtesy the inner loop).

for /? is what anyone interested should really be looking at for more help (note that in batch files the % signs are doubled):

%~I  - expands %I removing any surrounding quotes (")
%~dI - expands %I to a drive letter only
%~pI - expands %I to a path only

So what does "%%~dpa%%i" mean? Suppose one of the .REP files located by the dir command is "C:\Reports folder\123-Chemistry-101.rep".

%%~dpa would mean the drive letter and path of the file minus the surrounding quotes, i.e. C:\Reports folder\.

%%i would, as I noted above, be the folder name extracted from the file name (anything between two hyphen delimiters), so in this case Chemistry.

Putting it all together, "%%~dpa%%i" would for this file expand to "C:\Reports folder\Chemistry", because that's where we want the file to be moved to.

Karan
  • 56,477
  • Note: It works even if .REP files are present in sub-folders of Reports folder and will create subject name sub-folders at each level where it finds such files. – Karan May 22 '15 at 03:21
  • that is very good but i'd give an explanatory comment to help in reading the thing, that where you write %%~dpa%%i In the %%~dpa part the 'a' is a variable and d and p are codes. And the reader should know that the %~ or %%~ codes don't(as far as I can tell) ever end in %, So the reader should look at what is %%~dpa then what is %%i There is a code 'a' e.g. %~a1 which displays a file's attributes. So just clarifying that your 'a' is the variable a. Sometimes things get so complex with batch I have to echo and run it to figure it out even things about the language! Good stuff – barlop May 22 '15 at 05:15
  • @barlop: I added some stuff but really people are going to have to study for /? and as you said debug the file by using echos liberally. There's a limit to what one can explain here, and some effort will be required on the part of the reader. – Karan May 22 '15 at 05:22
  • You write "the inner loop" <--- it tokenizes a string but I guess there's no iteration there in that inner for statement, in which case, i'd think the inner for statement isn't much of a loop. Though technically I think you're right it's a loop, but because it could potentially deal with multiple items – barlop May 22 '15 at 06:19
  • @barlop: If you look at it as a for-do loop, then the second loop does have a body, and the first loop's body consists of the second loop. Anyway there's no point getting hung up on such trivialities IMO. It makes no difference to the understanding of the code as far as I'm concerned. – Karan May 22 '15 at 06:55
  • Well obviously I was not denying that the for statements have a body. I think you misunderstood me if you thought I was. – barlop May 22 '15 at 07:00
  • @barlop: No misunderstanding, I got exactly where you were coming from. The inner for-do loop's body doesn't execute multiple times in this case, but it can. Thus we still call it a loop. We're on the same page. :) – Karan May 22 '15 at 07:05