I'm looking to be able to supply a drive letter and get back the disk GUID within a Windows command script. From the command line I can do the following but I am not sure how to script this:
diskpart
list disk
select disk #
uniqueid disk
The closest I could find was this snippet that pulls the volume number based on the drive letter but I believe there would need to be a nested loop to select each of the disks and I can't figure out how to incorporate that:
for /f "tokens=2,3" %%a in ('echo list volume ^| diskpart') do (
if %%b==%driveletter% (
echo Volume number is %%a
)
)
Also since list disk doesn't specify the volume letters there would need to be something translating the disk # to the volume #, is that even possible?
Besides select volume 1, you can also use select volume C or selct volume C: (note the response mentions the corresponding volume number).
Also you don't have to find and select the corresponding disk manually. Uniqueid disk translates the selected volume to the disk.
This makes it quite easy:
#echo off
setlocal
set "Drive=C:"
for /f "tokens=2 delims={}" %%a in ('(echo select volume %Drive%^&echo uniqueid disk^)^|diskpart') do set "GUID=%%a"
echo Disk GUID for %Drive% is %guid%
Based on the discussion with Compo, I adapted the for loop to take care of the different output with MBR vs. GPT drives:
#echo off
setlocal
set "Drive=C:"
for /f "delims=" %%a in ('(echo select volume %Drive%^&echo uniqueid disk^)^|diskpart^|find ":"') do (
for %%b in (%%a) do set "GUID=%%b"
)
echo Disk GUID for %Drive% is %guid%
With this change, the output format now looks either like:
Disk GUID for C: is {DC8DD71C-31B8-4B04-9FB6-C66A325B738B}
or like:
Disk GUID for F: is DB72E293
I made a small batch file to copy the contents of a drive to external storage, but obviously, there is many different letters that can be assigned to an external disc/drive.
Basically I want to do something similar to
if exist E: (
set "destination=E:"
) else (
set "destination=F:"
) else (
set "destination=G:"
Another thing I would like to know is how can you check if the storage is over a certain amount or under a certain amount? I ask this because the usual letters are C and D for Windows partitions, or C and D for partition and a CD/DVD reader.
Obviously a CD/DVD reader has no storage, so if it would be greater than the storage specified it would got to the next else and keep going setting %destination% to the next letter. I have thought of checking to see if it's USB or CD/DVD, as you can make E, F, G partitions on your internal drive, but I have no clue how.
Here is what the original file looks like, just in case you want to know what I am doing:
#echo off
title Backup
REM Here is where I will place the code to check for drives
set "srcd=E:\"
REM Here is my destination, the computers partition for C.
set "destd=C:"
REM It will then be set to this, dir is where I make logs etc, dir2 is where I will copy the files to, log is obviously, a text file.
set "dir=%destd%\BackupUSB"
set "dir2=%destd%\%dir%\Files"
set "log=%dir%\Log.txt"
REM I am now finding if the destination exists as it will be copied to a folder, if it does not exist I will make it..
if exist "%dir2%" (
cd "%dir%"
) else (
md "%dir2%"
)
REM I am now going to create the log file saying the date and time the transfer took place.
for /f "tokens=*" %%a in ('date /t') do (
set d=%%a
)
for /f "tokens=*" %%a in ('time /t') do (
set t=%%a
)
REM Add date and time to show on same line.
set "dt=%d%%t%"
REM I now write the text to the file.
echo ==================>>"%log%"
echo =%dt%=>>"%log%"
echo ==================>>"%log%"
REM if the source exists copy the files, if not then save a message to a text file saying it failed.
if exist "%srcd%" (
cd %srcd%
REM /Q copies silently.
echo please wait while your files are copied from %srcd% to %dir2%
xcopy "%srcd%" /E /I /Q /H "%dir2%" /y
echo Copied "%srcd%" to "%dir2%" [%dt%]>>"%log%"
) else (
echo Failed to copy files from drive %srcd% to "%dir2%" please check the drive/path exists and run the batch file again [%dt%]>>"%log%"
)
Hello I have a batch file I've created to delete all files of a certain extension that it asks for when you run it. I need to delete 2,111,000 .txt files and the batch file only deletes 3 at a time which will take forever to delete the files. Is there a way I can make it faster or if somebody has a better code to do this?
Here is my code:
#ECHO OFF
CLS
SET found=0
ECHO Enter the file extension you want to delete...
SET /p ext="> "
IF EXIST *.%ext% ( rem Check if there are any in the current folder :)
DEL *.%ext%
SET found=1
)
FOR /D /R %%G IN ("*") DO ( rem Iterate through all subfolders
IF EXIST %%G CD %%G
IF EXIST *.%ext% (
DEL *.%ext%
SET found=1
)
)
IF %found%==1 (
ECHO.
ECHO Deleted all .%ext% files.
ECHO.
) ELSE (
ECHO.
ECHO There were no .%ext% files.
ECHO Nothing has been deleted.
ECHO.
)
PAUSE
EXIT
Can I make this go faster?
The quickest way I can imagine is just:
cd /BASE_PATH
del /s *.txt
You're probably better just letting the OS sequentially delete files rather than trying to delete multiple files in parallel anyways. If you're using a mechanical HDD as opposed to an SSD, you could have files on different platters, heads, sectors, etc, and depending how much load you put on an I/O bound resource, the overall operation takes more time since the drive has to seek data all over the place. Plus, random access on an HDD is abysmal.
You might want to try it this way:
DIR C:\*.txt /S /B > filelist
FOR /f %%i in (filelist) DO ECHO DELETE %%i
Remove the 'ECHO' when you are sure you want to run this ;-)
But this only makes sense when you want to process each file separately, for logging purposes for example. If not, then #Dogbert solution is shorter.
I created a windows batch file to read all the about 10000 *.txt files (containing a header and 2 tab separated columns of data, 2048 lines) in my folder, creating a text file table by concatenating their 2nd columns. But my approach seems to be quite slow
For this purpose i use for-loops to go through the commands ('TYPE !fileName!') and ('TYPE !fileName! ^| FINDSTR "^[0-9]"'). I first read the second column of a *.txt file. Then store this in a temporary file with a for-loop:
SET firstLine=true
FOR /F "delims= tokens=2" %%G IN ('TYPE !fileName! ^| FINDSTR "^[0-9]"') DO (
IF !firstLine!==true (
ECHO %%G > !tmpFile!
SET firstLine=false
) ELSE (
ECHO %%G >> !tmpFile!
)
)
afterwards I read the currentTable together with the temporary file and write out to the currentTable file, appending one column
SET firstLine=true
(
FOR /F "tokens=*" %%G IN ('TYPE !currenTable!') DO (
SET /P line=
IF !firstLine!==true (
ECHO %%G !line! > !currenTable!
SET firstLine=false
) ELSE (
ECHO %%G !line! >> !currenTable!
)
)
)<!tmpFile!
Edit (due to comments)
A data file would look like this:
some header
col1 col2
12.3 1.2E3
12.4 1.3E3
12.5 1.4E3
And what I want will be this
some header
col1File1 col2File1 col2File2 col2File3 col2File4 ...
12.3 1.2E3 2.2E3 3.2E3 4.2E3 ...
12.4 1.3E3 2.3E3 3.3E3 4.3E3 ...
12.5 1.4E3 2.4E3 3.4E3 4.4E3 ...
where in both cases columns are separated with tabs.
Questions:
1) the 'TYPE' command (especially combined with the 'FINDSTR' command) seems to be quite slow. Is there some trick to read the file faster?
EDIT: solved, by using only 'FINDSTR' and 'FOR'-loop directly through file, script performance seems to lag at the file write process (due to appending). Any suggestions to avoid the appending (and avoiding troubles with maximum variable size)?
2) Is there some possibility to avoid writing temporary files? Like is there some dummy-stream you can write to and pick from afterwards? I did not find anything like this on the web.
Is there a way to get the amount of free diskspace of a disk or a folder in a CMD
without having to install some thirdparty applications?
I have a CMD that copies a big file to a given directory and could of course use
the errorlevel return from the copy command, but then I have to wait for the time
it takes to copy the file (eg...to that then the disk is full and the copy operation fails).
I would like to know before I start the copy if it is any idea at all. Tried the DU.EXE utility from Sysinternals, but that show occupied space only.
If you run "dir c:\", the last line will give you the free disk space.
Edit:
Better solution: "fsutil volume diskfree c:"
A possible solution:
dir|find "bytes free"
a more "advanced solution", for Windows Xp and beyond:
wmic /node:"%COMPUTERNAME%" LogicalDisk Where DriveType="3" Get DeviceID,FreeSpace|find /I "c:"
The Windows Management Instrumentation Command-line (WMIC) tool (Wmic.exe)
can gather vast amounts of information about about a Windows Server 2003 as well as Windows XP or Vista. The tool accesses the underlying hardware by using Windows Management Instrumentation (WMI). Not for Windows 2000.
As noted by Alexander Stohr in the comments:
WMIC can see policy based restrictions as well. (even if 'dir' will still do the job),
'dir' is locale dependent.
Using this command you can find all partitions, size & free space: wmic logicaldisk get size, freespace, caption
You can avoid the commas by using /-C on the DIR command.
FOR /F "usebackq tokens=3" %%s IN (`DIR C:\ /-C /-O /W`) DO (
SET FREE_SPACE=%%s
)
ECHO FREE_SPACE is %FREE_SPACE%
If you want to compare the available space to the space needed, you could do something like the following. I specified the number with thousands separator, then removed them. It is difficult to grasp the number without commas. The SET /A is nice, but it stops working with large numbers.
SET EXITCODE=0
SET NEEDED=100,000,000
SET NEEDED=%NEEDED:,=%
IF %FREE_SPACE% LSS %NEEDED% (
ECHO Not enough.
SET EXITCODE=1
)
EXIT /B %EXITCODE%
UPDATE:
Much has changed since 2014. Here is a better answer. It uses PowerShell which is available on all currently supported Microsoft Windows systems.
The code below would be much clearer and easier to understand if the script were written in PowerShell without using cmd.exe as a wrapper. If you are using PowerShell Core, change powershell to pwsh.
SET "NEEDED=100,000,000"
SET "NEEDED=%NEEDED:,=%"
powershell -NoLogo -NoProfile -Command ^
$Free = (Get-PSDrive -Name 'C').Free; ^
if ($Free -lt [int64]%NEEDED%) { exit $true } else { exit $false }
IF ERRORLEVEL 1 (
ECHO "Not enough disk space available."
) else (
ECHO "Available disk space is adequate."
)
df.exe
Shows all your disks; total, used and free capacity. You can alter the output by various command-line options.
You can get it from http://www.paulsadowski.com/WSH/cmdprogs.htm, http://unxutils.sourceforge.net/ or somewhere else. It's a standard unix-util like du.
df -h will show all your drive's used and available disk space. For example:
M:\>df -h
Filesystem Size Used Avail Use% Mounted on
C:/cygwin/bin 932G 78G 855G 9% /usr/bin
C:/cygwin/lib 932G 78G 855G 9% /usr/lib
C:/cygwin 932G 78G 855G 9% /
C: 932G 78G 855G 9% /cygdrive/c
E: 1.9T 1.3T 621G 67% /cygdrive/e
F: 1.9T 201G 1.7T 11% /cygdrive/f
H: 1.5T 524G 938G 36% /cygdrive/h
M: 1.5T 524G 938G 36% /cygdrive/m
P: 98G 67G 31G 69% /cygdrive/p
R: 98G 14G 84G 15% /cygdrive/r
Cygwin is available for free from: https://www.cygwin.com/
It adds many powerful tools to the command prompt. To get just the available space on drive M (as mapped in windows to a shared drive), one could enter in:
M:\>df -h | grep M: | awk '{print $4}'
The following script will give you free bytes on the drive:
#setlocal enableextensions enabledelayedexpansion
#echo off
for /f "tokens=3" %%a in ('dir c:\') do (
set bytesfree=%%a
)
set bytesfree=%bytesfree:,=%
echo %bytesfree%
endlocal && set bytesfree=%bytesfree%
Note that this depends on the output of your dir command, which needs the last line containing the free space of the format 24 Dir(s) 34,071,691,264 bytes free. Specifically:
it must be the last line (or you can modify the for loop to detect the line explicitly rather than relying on setting bytesfree for every line).
the free space must be the third "word" (or you can change the tokens= bit to get a different word).
thousands separators are the , character (or you can change the substitution from comma to something else).
It doesn't pollute your environment namespace, setting only the bytesfree variable on exit. If your dir output is different (eg, different locale or language settings), you will need to adjust the script.
Using paxdiablo excellent solution I wrote a little bit more sophisticated batch script, which uses drive letter as the incoming argument and checks if drive exists on a tricky (but not beauty) way:
#echo off
setlocal enableextensions enabledelayedexpansion
set chkfile=drivechk.tmp
if "%1" == "" goto :usage
set drive=%1
set drive=%drive:\=%
set drive=%drive::=%
dir %drive%:>nul 2>%chkfile%
for %%? in (%chkfile%) do (
set chksize=%%~z?
)
if %chksize% neq 0 (
more %chkfile%
del %chkfile%
goto :eof
)
del %chkfile%
for /f "tokens=3" %%a in ('dir %drive%:\') do (
set bytesfree=%%a
)
set bytesfree=%bytesfree:,=%
echo %bytesfree% byte(s) free on volume %drive%:
endlocal
goto :eof
:usage
echo.
echo usage: freedisk ^<driveletter^> (eg.: freedisk c)
note1: you may type simple letter (eg. x) or may use x: or x:\ format as drive letter in the argument
note2: script will display stderr from %chkfile% only if the size bigger than 0
note3: I saved this script as freedisk.cmd (see usage)
I make a variation to generate this out from script:
volume C: - 49 GB total space / 29512314880 byte(s) free
I use diskpart to get this information.
#echo off
setlocal enableextensions enabledelayedexpansion
set chkfile=drivechk.tmp
if "%1" == "" goto :usage
set drive=%1
set drive=%drive:\=%
set drive=%drive::=%
dir %drive%:>nul 2>%chkfile%
for %%? in (%chkfile%) do (
set chksize=%%~z?
)
if %chksize% neq 0 (
more %chkfile%
del %chkfile%
goto :eof
)
del %chkfile%
echo list volume | diskpart | find /I " %drive% " >%chkfile%
for /f "tokens=6" %%a in ('type %chkfile%' ) do (
set dsksz=%%a
)
for /f "tokens=7" %%a in ('type %chkfile%' ) do (
set dskunit=%%a
)
del %chkfile%
for /f "tokens=3" %%a in ('dir %drive%:\') do (
set bytesfree=%%a
)
set bytesfree=%bytesfree:,=%
echo volume %drive%: - %dsksz% %dskunit% total space / %bytesfree% byte(s) free
endlocal
goto :eof
:usage
echo.
echo usage: freedisk ^<driveletter^> (eg.: freedisk c)
Is cscript a 3rd party app?
I suggest trying Microsoft Scripting, where you can use a programming language (JScript, VBS) to check on things like List Available Disk Space.
The scripting infrastructure is present on all current Windows versions (including 2008).