Skip to content
View in the app

A better way to browse. Learn more.

MSFN

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

Batch script list drives.

Featured Replies

The following script works as expected but I'd like an explanation of why the command CMD /C is necessary for it to run if the drive list contains drive a.

This works:

@echo off
cls
setlocal

for %%1 in (a b c d e f g h i j k l m n o p q r s t u v w x y z) do (
cmd /c if exist %%1:\ (
fsutil fsinfo drivetype %%1:
)
)

This hangs with a "no disk in drive" error message.

@echo off
cls
setlocal

for %%1 in (a b c d e f g h i j k l m n o p q r s t u v w x y z) do (
if exist %%1:\ (
fsutil fsinfo drivetype %%1:
)
)

I added some "ELSE" logic, give it a try.

@echo off
cls
setlocal

for %i in (a b c d e f g h i j k l m n o p q r s t u v w x y z) do (if exist %i:\ (fsutil fsinfo drivetype %i: )ELSE (fsutil fsinfo drivetype %i:))

The CMD /C tells your script to give up when your if exist statement fails, which does not happen in your second script because it does not have a 'ELSE' block.

/C Carries out My_Command and then terminates

More Details Here and Here

Edited by MrJinje

Try reversing the logic of it.

Fsutil does NOT throw an error if a drive is not accessible, BUT it will report an error message.

In my Italian XP this error is "Directory principale non esistente"

Thus this works:

@ECHO OFF

for %%1 in (a b c d e f g h i j k l m n o p q r s t u v w x y z) do (
fsutil fsinfo drivetype %%1: |FIND /V "Directory")

jaclaz

You can use DISKPART too, I feel it's a better tool for this type of thing:

C:\> ECHO LIST VOL | DISKPART | FIND "NTFS"
Volume 1 C System NTFS Partition 20 GB Healthy System

Replace NTFS with CDFS to find the CDROM's. You'll have to do some parsing of the results, but this is cleaner and quicker than most methods.

Edited by Noise

You could also get this incredibly easily with Win32_LogicalDisk from WMI and some vbscript:

RunMeWithCscript()

strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\CIMV2")
Set colDiskItems = objWMIService.ExecQuery( _
"SELECT * FROM Win32_LogicalDisk",,48)

For Each objDiskItem in colDiskItems
If objDiskItem.DriveType = 3 Then
Wscript.Echo " Volume: " & objDiskItem.Caption
Wscript.Echo " Drive Type: " & objDiskItem.Description
Wscript.Echo " Compressed: " & objDiskItem.Compressed
Wscript.Echo " File System: " & objDiskItem.FileSystem
Wscript.Echo " Volume Size: " & FormatNumber(objDiskItem.Size/1024^3, 2) & " GB"
Wscript.Echo " Free Space: " & FormatNumber(objDiskItem.FreeSpace/1024^3, 2) & " GB"
Wscript.Echo " VolumeDirty: " & objDiskItem.VolumeDirty
Wscript.Echo " VolumeSerialNumber: " & objDiskItem.VolumeSerialNumber
Wscript.Echo ""
End If

If objDiskItem.DriveType = 5 Then
Wscript.Echo " Volume: " & objDiskItem.Caption
Wscript.Echo " Drive Type: " & objDiskItem.Description
If Not objDiskItem.FileSystem = "" Then
Wscript.Echo " File System: " & objDiskItem.FileSystem
Wscript.Echo " Volume Size: " & FormatNumber(objDiskItem.Size/1024^3, 2) & " GB"
Wscript.Echo " Free Space: " & FormatNumber(objDiskItem.FreeSpace/1024^3, 2) & " GB"
End If
Wscript.Echo ""
End If

If objDiskItem.DriveType = 2 Then
Wscript.Echo " Volume: " & objDiskItem.Caption
Wscript.Echo " Drive Type: " & objDiskItem.Description
If Not objDiskItem.FileSystem = "" Then
Wscript.Echo " File System: " & objDiskItem.FileSystem
Wscript.Echo " Volume Size: " & FormatNumber(objDiskItem.Size/1024^3, 2) & " GB"
Wscript.Echo " Free Space: " & FormatNumber(objDiskItem.FreeSpace/1024^3, 2) & " GB"
End If
Wscript.Echo ""
End If
Next


'//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'// Subroutine: RunMeWithCScript()
'//
'// Purpose: Forces the currently running script to use Cscript.exe as the Script
'// engine. If the script is already running with cscript.exe the sub exits
'// and continues the script.
'//
'// Sub Attempts to call the script with its original arguments. Arguments
'// that contain a space will be wrapped in double quotes when the script
'// calls itself again. To verify your command string you can echo out the
'// scriptCommand variable.
'//
'// Usage: Add a call to this sub (RunMeWithCscript) to the beggining of your script
'// to ensure that cscript.exe is used as the script engine.
'//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Public Sub RunMeWithCScript()

Dim scriptEngine, engineFolder, Args, arg, scriptName, argString, scriptCommand

scriptEngine = Ucase(Mid(Wscript.FullName,InstrRev(Wscript.FullName,"\")+1))
engineFolder = Left(Wscript.FullName,InstrRev(Wscript.FullName,"\"))
argString = ""

If scriptEngine = "WSCRIPT.EXE" Then
Dim Shell : Set Shell = CreateObject("Wscript.Shell")
Set Args = Wscript.Arguments

For each arg in Args 'loop though argument array as a collection to rebuild argument string
If instr(arg," ") > 0 Then arg = """" & arg & """" 'if the argument contains a space wrap it in double quotes
argString = argString & " " & Arg
Next

'Create a persistent command prompt for the cscript output window and call the script with its original arguments
scriptCommand = "cmd.exe /k " & engineFolder & "cscript.exe """ & Wscript.ScriptFullName & """" & argString

Shell.Run scriptCommand,,False
Wscript.Quit
Else
Exit Sub 'Already Running with Cscript Exit this Subroutine
End If
End Sub

Well, if order of columns is not a problem, a one-liner is possible at WMIC too:

wmic.exe path Win32_Logicaldisk Get description^, name

To change the order of the column is trickier that it might seem:

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
FOR /f "tokens=2,3 delims=," %%A IN ('wmic.exe path Win32_Logicaldisk Get name^, description /FORMAT:csv.xsl') DO (
SET Tempvar=%%A,%%B
FOR /F "tokens=1,2 delims=," %%C IN ('ECHO !TempVar!') DO ECHO %%D %%C
)

jaclaz

Well, if order of columns is not a problem, a one-liner is possible at WMIC too:

wmic.exe path Win32_Logicaldisk Get description^, name

To change the order of the column is trickier that it might seem:

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
FOR /f "tokens=2,3 delims=," %%A IN ('wmic.exe path Win32_Logicaldisk Get name^, description /FORMAT:csv.xsl') DO (
SET Tempvar=%%A,%%B
FOR /F "tokens=1,2 delims=," %%C IN ('ECHO !TempVar!') DO ECHO %%D %%C
)

jaclaz

Or:
@FOR /F "TOKENS=* DELIMS=," %%# IN ('WMIC LOGICALDISK GET NAME^, DESCRIPTION^
/FORMAT:CSV^|FIND ":"') DO @FOR /F "TOKENS=2,3 DELIMS=," %%A IN ("%%#"
) DO @ECHO %%B %%A)

  • Author

Cluberti - Yes, the script runs without error when Cmd /k is used.

Thanks to all for your interest and responses.

V.

Cluberti - Yes, the script runs without error when Cmd /k is used.

Thanks to all for your interest and responses.

V.

That would mean indeed it's because the check for A is failing in fsutil, and using /C or /K causes a new cmd.exe process to spawn to do the check, which will return to the original cmd.exe to continue the next step in the loop regardless of whether or not the previous operation failed or not. Using cmd without switches means it runs the check in the same cmd.exe process, and thus the fsutil command being stuck will block the rest of the drive letters from being parsed. I would suggest using the vbscript I posted above, the wmic command from jaclaz or Yzowl if you must do this in a .cmd file, or make sure you call this with cmd /c or /k.

That would mean indeed it's because the check for A is failing in fsutil, and using /C or /K causes a new cmd.exe process to spawn to do the check, which will return to the original cmd.exe to continue the next step in the loop regardless of whether or not the previous operation failed or not. Using cmd without switches means it runs the check in the same cmd.exe process, and thus the fsutil command being stuck will block the rest of the drive letters from being parsed. I would suggest using the vbscript I posted above, the wmic command from jaclaz or Yzowl if you must do this in a .cmd file, or make sure you call this with cmd /c or /k.

Well, no, as said, it's not fsutil the problem, as it runs normally on non existing drives it's the "if exist" check.

jaclaz

it's not fsutil the problem, as it runs normally on non existing drives it's the "if exist" check.

That is correct, if anyone looks at my post, the fix was to run FSUTIL during the else statement. :whistle:


for %i in (a b c d e f g h i j k l m n o p q r s t u v w x y z) do (if exist %i:\ (fsutil fsinfo drivetype %i: )ELSE (fsutil fsinfo drivetype %i:))

Edited by MrJinje

That is correct, if anyone looks at my post, the fix was to run FSUTIL during the else statement. :whistle:

Well, if anyone looks at my post ;), the if exist is NOT needed at all, the usual form of IF/THEN/ELSE is:

IF <condition is true> THEN <do this> ELSE <do that>

something like:

IF <condition is true> THEN <do this> ELSE <do this>

seems to me a little pointless, and all in all replaceable by:

<do this>

:P

jaclaz

Edited by jaclaz

Create an account or sign in to comment

Recently Browsing 0

  • No registered users viewing this page.

Account

Navigation

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.