0

I'm trying to make a simple script that will output the names of all subfolders, except for one. I'm having trouble doing the string comparison to remove that one folder.

Here's a basic folder breakdown:

  • C
    • Backup
      • .sync
      • folder1
      • folder2

Here's a basic example of code that works 90%:

ForFiles /P C:\Backup /C "CMD /C echo @FILE"

And here's the output of this command (the quotation marks are in the output itself):

".sync"
"folder1"
"folder2"

To give a brief explanation of the code, basically ForFiles will run through the files and subfolders at the given path (specified by /P C:\Backup). /C then specifies a command, which is in double quotes - echo @FILE will then output the name of the file. The actual code I'm running is more complex than this, but this will suffice as a minimum example showing my problem. I do not want to output the name of the .sync folder, because it's used by another program and should not be touched.

So, what I want to do is put an "if" statement in the command, so that not everything will be output. In pseudocode, this would be "if the name of the folder is not .sync, output the name of the folder". However, this appears to be more complex because of the quotation marks, which I guess I have to escape - but I have not had any luck with it. Here are some things I've tried:

  • Outputs all files, including .sync:
    • ForFiles /P C:\Backup /C "CMD /C if NOT @FILE == .sync echo @FILE"
    • ForFiles /P C:\Backup /C "CMD /C if NOT @FILE == ".sync" echo @FILE"
    • ForFiles /P C:\Backup /C "CMD /C if NOT @FILE == '.sync' echo @FILE"
  • Gives an error because of the double double quotes (one method of escaping the double quotes, found on Stack Overflow)
    • ForFiles /P C:\Backup /C "CMD /C if NOT @FILE == "".sync"" echo @FILE"
  • Outputs all files, including .sync - using the ^ symbol was the other method of escaping double quotes I found on Stack Overflow, and it appears only the first one is actually being escaped for some reason
    • ForFiles /P C:\Backup /C "CMD /C if NOT @FILE == ^".sync^" echo @FILE"

Can anyone give me some advice on howq to acocomplish this? Thanks!

aschipfl
  • 33,626
  • 12
  • 54
  • 99
Jake
  • 3,142
  • 4
  • 30
  • 48
  • Not sure why you are using FORFILES. The FOR command will work just fine and will run faster. – Squashman Jan 02 '16 at 00:15
  • Thanks for the advice - fortunately for me, there aren't all that many files to go through, so FORFILES works fine as far as speed. I'm using it because I found it in an answer here: http://stackoverflow.com/questions/51054/batch-file-to-delete-files-older-than-n-days - Although the script in my question does not mention the "delete files older than N days" part, that's what I want my script to do in the end. – Jake Jan 02 '16 at 00:54

3 Answers3

1
ForFiles /P u:\Backup /C "CMD /C echo @FILE|find /v /i "".sync"""

worked for me, using my u: drive. No doubt it would also filter out *.sync* - if that's or any concern.

Magoo
  • 77,302
  • 8
  • 62
  • 84
  • Works perfectly! Piping into the 'find' command, and using double double quotes - definitely not something I would have tried. The resulting triple double quotes at the end is pretty ugly...but I guess that's what I get for going with a batch script! Thank you very much! – Jake Jan 01 '16 at 22:29
0

To escape the double-quotes within the command after the /C switch of forfiles, you have got two possibilities:

forfiles /P "C:\Backup" /C "CMD /C if @isdir==TRUE if /I not @file==\".sync\" echo @file"

forfiles /P "C:\Backup" /C "CMD /C if @isdir==TRUE if /I not @file==0x22.sync0x22 echo @file"

The first variant is perhaps more obvious, but poorly documented.

The second variant uses the hexadecimal character code of ". Although this might be more difficult to read, I recommend this method, because this hides the nested quotes from the command interpreter cmd; the \" variant might confuse cmd as the \ escaping applies to forfiles but not to cmd, so it recognises the ".

I stringly recommend to add the switch /I to the if command to do the comparison of file/directory paths in a case-insensitive manner, because Windows does not care about the case in paths.

As you can see I have inserted another if statement: I preceded the entire command line with if @isdir==TRUE, to filter out all files, as you are trying to output a list of folders (directories) only.

aschipfl
  • 33,626
  • 12
  • 54
  • 99
0

I understand that you simply want to list all the dirs under C:\Backup except the .sync one, am I right? Here's the code to do it:

dir /ad /b C:\Backup | find /V ".sync"
Henrik
  • 332
  • 3
  • 12