Page 1 of 1

[SOLVED] Validating user input against the content of a text file

Posted: 21 Oct 2023 21:14
by Quisquose
I am trying to semi-automate a diskpart command, and then have the output of this command formatted to my liking.

I am very inexperienced with command line stuff, but I have managed to get some code together using various online examples (rather than me writing it myself). It works and it does exactly what I want, except for one problem: user input validation.

The script requires the user to input a number to select a disk. I would like to check this user input and only proceed if a valid number is entered.

The first part of the user input validation works fine (it rejects anything that is not a number). But the second part of the validation (ensuring that the entered number matches one of the existing disk numbers) is the part that is not working correctly. Apart from that one input validation issue, everything else in the script is fine, and works how I want it to.

The contents of a text file (%temp%\output.txt) is what determines whether a number is considered valid or not.

Example of output.txt content:

Code: Select all

Microsoft DiskPart version 6.1.7601
  Disk ###  Status         Size     Free     Dyn  Gpt
  Disk 0    Online          476 GB      0 B         
  Disk 1    Online         1863 GB  2048 KB         
  Disk 2    Online         3726 GB      0 B        *
  Disk 3    Online         7640 MB      0 B      
If the contents of %temp%\output.txt is as shown above, then valid input numbers should be either: 0 1 2 or 3 because the output text file contains entries for: Disk 0, Disk 1, Disk 2 and Disk 3.

The validation section of code that I cobbled together (see below) kind of works, but it always rejects the highest disk number as invalid. To clarify: in the example text file shown above, inputting the number 3 should be valid (because there is a Disk 3 entry) but my code rejects it.

Similarly, if the output text file were to have 3 disks listed instead of 4 (i.e. Disk 0, Disk 1, Disk 2) then only 0 or 1 will be accepted as valid. If I enter the number 2 it gets rejected as invalid even though it should be valid. Again, it's the highest numbered disk in the list that seems to always get incorrectly identified as invalid.

Unfortunately I only have the vaguest notion of what the validation line of code is doing. I don't understand tokens and the like, so that's why I am struggling to fix this issue.

Here is my script:

Code: Select all

@CLS
@echo off
setlocal EnableDelayedExpansion
::define a variable containing a single backspace character (to allow spaces to display at beginning of line)
for /f %%A in ('"prompt $H &echo on &for %%B in (1) do rem"') do set BS=%%A
echo list disk > %temp%\diskpart.txt
echo.
echo   File System Cluster Size
echo.  ------------------------
diskpart /s %temp%\diskpart.txt | findstr "Disk ###" > %temp%\output.txt
echo.
type %temp%\output.txt | findstr /V /C:"Microsoft DiskPart"
echo.
:disk
set /p disk=%BS%  Select a disk by entering its number: 
echo %disk%|findstr /r "^[0-9]*$" >nul || (
    echo.
    echo   You did not enter a number.
    echo.
    goto disk
)
echo.
set "valid_disks="
for /f "tokens=2" %%a in ('type %temp%\output.txt ^| findstr /r /c:"Disk [0-9]*"') do (
    set "disk_num=%%a"
    set "disk_num=!disk_num: =!"
    set "valid_disks=!valid_disks! !disk_num!"
)
if "!valid_disks: %disk% =!"=="!valid_disks!" (
    echo.
    echo   There is no disk with this number.
    echo.
    goto disk
)   

My script continues after this to basically do the same again for partition numbers, and then it combines the two validated numbers to send a command and display the output formatted to my liking. All of that works fine, it's just the input validation that is the issue. I can post the whole script if necessary, but the section above is where the problem lies (specifically the "valid_disks=" section).

Thanks for any help that anyone is able to offer.

___________________________________________________________________________________________________________________

Code: Select all

 INFO.BAT version 1.6
--------------------------------------------------------------------------------
Windows version        :  Microsoft Windows [Version 6.1.7601]
Product name           :  Windows 7 Professional, 64 bit
Performance indicators :  Processor Cores: 8      Visible RAM: 16692744 kilobytes

Date/Time format       :  (dd/mm/yy)  22/10/2023   3:36:30.94
__APPDIR__             :  C:\Windows\system32\
ComSpec                :  C:\Windows\system32\cmd.exe
PathExt                :  .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC
Extensions             :  system: Enabled   user: Enabled 
Delayed expansion      :  system: Disabled  user: Disabled
Locale name            :  en-GB       Code Pages: OEM  850    ANSI 1252
DIR  format            :  20/10/2023  08:09    17,093,369,856 pagefile.sys
Permissions            :  Elevated Admin=Yes, Admin group=Yes

                          Missing from the tool collection:  debug

Re: Validating user input against the content of a text file

Posted: 21 Oct 2023 23:22
by Batcher
Remove one space in your code line 29.

Code: Select all

if "!valid_disks: %disk%=!"=="!valid_disks!" (

Re: Validating user input against the content of a text file

Posted: 22 Oct 2023 02:02
by OJBakker
Your code creates variable valid_disks with all valid disknumbers separated by spaces.
You test for valid disknumber by checking if the entered disknumber with a leading and a trailing space is found in the valid_disk variable.
The first disknumber in valid_disk will not have a leading space and the last disknumber will not have a trailing space so both will not be found by your code. The spaces are needed to make sure there is no conflict between single digit and multi-digit disknumbers.
You can solve this problem by adding a leading and trailing space to the valid_disk variable.
See the changes in the relevant lines below. Changes are commented with rem.

Code: Select all

set "valid_disks= " & rem leading space added
for /f "tokens=2" %%a in ('type %temp%\output.txt ^| findstr /r /c:"Disk [0-9]*"') do (
    set "disk_num=%%a"
    set "disk_num=!disk_num: =!"
    set "valid_disks=!valid_disks! !disk_num!"
)
set "valid_disks=!valid_disks! " & rem trailing space added
if "!valid_disks: %disk% =!"=="!valid_disks!" (

Re: Validating user input against the content of a text file

Posted: 23 Oct 2023 05:27
by Quisquose
Batcher wrote:
21 Oct 2023 23:22
Remove one space in your code line 29.

Code: Select all

if "!valid_disks: %disk%=!"=="!valid_disks!" (
Wow, thank you! Who knew that one space could cause such problems? I removed the space and everything now works correctly.

OJBakker wrote:
22 Oct 2023 02:02
Your code creates variable valid_disks with all valid disknumbers separated by spaces.
You test for valid disknumber by checking if the entered disknumber with a leading and a trailing space is found in the valid_disk variable.
The first disknumber in valid_disk will not have a leading space and the last disknumber will not have a trailing space so both will not be found by your code. The spaces are needed to make sure there is no conflict between single digit and multi-digit disknumbers.
You can solve this problem by adding a leading and trailing space to the valid_disk variable.
See the changes in the relevant lines below. Changes are commented with rem.

Code: Select all

set "valid_disks= " & rem leading space added
for /f "tokens=2" %%a in ('type %temp%\output.txt ^| findstr /r /c:"Disk [0-9]*"') do (
    set "disk_num=%%a"
    set "disk_num=!disk_num: =!"
    set "valid_disks=!valid_disks! !disk_num!"
)
set "valid_disks=!valid_disks! " & rem trailing space added
if "!valid_disks: %disk% =!"=="!valid_disks!" (
Thank you for this solution, and also for your accompanying explanation (which was very useful, seeing as this is the part of my script that I really did not understand at all). You've made things a lot clearer for me.