Can you put form elements in a batch file? I was curious when I saw it in Word 5.5 for DOS. I can't find out how to do it, but I know NOTHING about all that junk in an executable file for DOS. Can somebody please help me?
If you want to ask for free text in a batch file use:
SET /P UserName=What is your UserName?
This puts the user's response in an environment variable named UserName, which can be accessed with %UserName%
like this:
ECHO Hello, %UserName%. Welcome to planet Earth!
You can put any executable command in a batch file, hence you can do anything in a batch file. If you see anything terribly fancy (like windowing), you probably are looking at a third party program, rather than a command built into the command processor itself.
Off the top of my head, the closest thing to a form (something that you can select items from) that I can think of is the CHOICE command. To find out how to use it, type this at a command prompt:
CHOICE /?
Here's the description...
This tool allows users to select one item from a list
of choices and returns the index of the selected choice.
Here are some syntax examples...
CHOICE /?
CHOICE /C YNC /M "Press Y for Yes, N for No or C for Cancel."
CHOICE /T 10 /C ync /CS /D y
CHOICE /C ab /M "Select a for option 1 and b for option 2."
CHOICE /C ab /N /M "Select a for option 1 and b for option 2."
And here's a full example:
CHOICE /C:ABCDN /N /T:10 /D:N /M:"Format drive A:, B:, C:, D: or None?"
REM Note that ERRORLEVEL handlers must be in decreasing order...
IF ERRORLEVEL 5 SET DRIVE=None
IF ERRORLEVEL 4 SET DRIVE=drive D:
IF ERRORLEVEL 3 SET DRIVE=drive C:
IF ERRORLEVEL 2 SET DRIVE=drive B:
IF ERRORLEVEL 1 SET DRIVE=drive A:
ECHO You chose to format %DRIVE%
Related
Trying to find the difference. But when this powershell command is inside in the findstr, it fails. On its own, it returns the correct value. Also, without the loop, it returns the correct value.
echo:!newvalue!| findstr /R "^[0123456789][0123456789]\.[0123456789]$" >nul
if errorlevel 1 (
set newvalue=
) else (
FOR /F "usebackq delims=" %%i IN (`powershell -nop -c "'{0:n1}' -f (%newvalue% - 12.0)"`) DO (SET difference=%%i)
echo %difference%
)
Can anyone figure out what I'm missing/did wrong?
Thanks in advance.
I recommend reading How does the Windows Command Interpreter (CMD.EXE) parse scripts?
Windows command processor replaces all environment variable references using syntax %variable% inside a command block starting with ( and ending with matching ) already on parsing the command line using this command block. This means the command line echo %difference% inside ELSE branch command block of the IF command is modified by cmd.exe before command IF is executed at all. %difference% is replaced by current value of environment variable difference or an empty string in case of environment variable difference is not defined somewhere above the IF condition. In latter case echo is the command line remaining after parsing the command block and therefore shows status of command echoing instead of the string value assigned to environment variable difference in the command line above. The solution with already enabled delayed environment variable expansion is using echo !difference! in ELSE command block.
A solution for this floating point subtraction without usage of PowerShell can be seen below:
#echo off
setlocal EnableExtensions EnableDelayedExpansion
if defined NewValue goto Validate
:UserPrompt
set /P "NewValue=Enter value between 00.0 and 99.9: "
:Validate
echo:!NewValue!| %SystemRoot%\System32\findstr.exe /R "^[0123456789][0123456789]\.[0123456789]$" >nul
if errorlevel 1 set "NewValue=" & goto UserPrompt
for /F "tokens=1,2 delims=." %%I in ("%NewValue%") do set "PreComma=%%I" & set "PostComma=%%J"
set /A Difference=1%PreComma% - 112
set "Difference=%Difference%.%PostComma%"
echo Difference is: %Difference%
endlocal
After validating that the string assigned to environment variable NewValue indeed consists of two digits, a point and one more digit as requested and expected and described at How can I do a negative regex match in batch?, the floating point number string is split up on . into pre-comma and post-comma number strings.
The pre-comma number is subtracted by 12 using an arithmetic expression. But it must be taken into account that an integer number with a leading 0 is interpreted by cmd.exe on evaluation of the arithmetic expression as octal number. That is no problem for 00 to 07. But 08 and 09 would be invalid octal numbers and so Windows command processor would use value 0 resulting in a wrong subtraction result if simply set /A Difference=PreComma - 12 would have been used in batch file. The workaround is concatenating the string 1 with the pre-comma string to a number string in range 100 to 199 and subtract 112 to get the correct result.
The post-comma value does not need to be modified and so the Difference value is determined finally with concatenating the result of the arithmetic expression with the unmodified post-comma number string.
It is possible to get the Difference value also always with two digits by inserting following additional command lines above echo Difference is: %Difference%:
if %Difference:~0,1% == - (
if %Difference:~2,1% == . set "Difference=-0%Difference:~1%"
) else (
if %Difference:~1,1% == . set "Difference=0%Difference%"
)
This solution avoids also the problem that floating point result of PowerShell is formatted according to region and language settings. For example in Germany and Austria the decimal symbol is , and not . which means the subtraction result output by PowerShell for 15.3 - 12.0 is 3,3 and not 3.3.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
echo /?
endlocal /?
findstr /?
for /?
goto /?
if /?
set /?
setlocal /?
See also single line with multiple commands using Windows batch file.
This is not technically an answer, as you've already received and accepted one a perfectly good one.
It is just to allow you to visualise a method of taking the string from your file, splitting it at the decimal point and subtracting 12, from a whole number greater or equal to 12, (see the accepted answer for whole numbers less than 12), all without 'loops' or PowerShell
#Echo Off
Rem Create a variable from the first line of your file
Set /P "newvalue="<"file.tmp"
Echo [%newvalue%]
Rem Exit if the string 'value' does not exist in '%newvalue%'
If "%newvalue%"=="%newvalue:*value=%" Exit /B
Rem ReSet the variable to everything after the string 'value'
Set "newvalue=%newvalue:*value=%"
Echo [%newvalue%]
Rem ReSet the variable to everything up to the first 'space' character
Set "newvalue=%newvalue: ="&:"%"
Echo [%newvalue%]
Rem ReSet the variable, removing the unneeded leading '=' character
Set "newvalue=%newvalue:~1%"
Echo [%newvalue%]
Rem Set a new variable to the whole number, i.e. everything up to the first '.' character
Set "whole=%newvalue:.="&:"%"
Echo [%whole%]
Rem Set a new variable to the decimal, i.e. everything after the '.' character
Set "decimal=%newvalue:*.=%"
Echo [%decimal%]
Rem Subtract 12 from the whole number
Set /A remainder=100+whole-112
Echo [%remainder%]
Rem ReJoin the variables to show the difference
Echo [%remainder%.%decimal%]
Pause
Obviously in your script proper, you'd only need:
#Echo Off
Set /P "newvalue="<"file.tmp"
If "%newvalue%"=="%newvalue:*value=%" Exit /B
Set "newvalue=%newvalue:*value=%"
Set "newvalue=%newvalue: ="&:"%"
Set "newvalue=%newvalue:~1%"
Set "whole=%newvalue:.="&:"%"
Set "decimal=%newvalue:*.=%"
Set /A remainder=100+whole-112
Echo %remainder%.%decimal%
Pause
I have a batch file which prompts the user a few times. I am looking to automate that with powershell. Is there any way to do this? I would need something like this:
Start-Process $InstallDir\Install.bat "y,*,$Version,y,y,y,y,y,y,y,y,y,y,y,y,y"
Install.bat runs an installation and there are a total of 16 prompts. The third I would like the be a variable that I have in my powershell script already, but the others will be static. Also, at the end of the script, you need to press any key to continue.
Is there any way to do this?
Depending on your batch file and what commands actually do the prompt, you might use input redirection <. Put the prompts into a text file pine by line and redirect that into your batch file.
Supposing the batch file prompts.bat contains the following commands...:
#echo off
set /P VAR="Please enter some text: "
echo/
echo Thank you for entering "%VAR%"!
choice /M "Do you want to continue "
if not ErrorLevel 2 del "%TEMP%\*.*"
pause
...and the text file prompts.txt contains the following lines...:
hello world
Y
n
End
...the console output of the command line prompts.bat < prompts.txt would be:
Please enter some text:
Thank you for entering "hello world"!
Do you want to continue [Y,N]?Y
C:\Users\operator\AppData\Local\Temp\*.*, Are you sure (Y/N)?
C:\Users\operator\AppData\Local\Temp\*.*, Are you sure (Y/N)? n
Press any key to continue . . .
(The del command shows two prompts here as it receives the RETURN behind Y which is not consumed by choice; since an empty entry is not accepted, the prompt appears one more time.)
Read-Host will display a prompt for entry, assigning it to a variable means you can then use that entry later in the script.
As your example is non-specific the below will only give you an idea of what you need to do.
$InstallDir = "C:\folder"
$Version = Read-Host -Prompt "Enter Version Number"
Start-Process "$InstallDir\Install.bat" -ArgumentList "y,*,$Version,y,y,y,y,y,y,y,y,y,y,y,y,y"
The below commands (with debug lines added - indented) should only redirect the echo's output to a file, should it already exist, according to my understanding.
However, it would seem that if exist %test0% always fills the file (creating it if non-existant) with the echo's output.
Does anyone know what is wrong?
#echo off
type test.bat
set test0="e:\documents and settings\administrator\desktop\test.log"
echo.&echo.
if exist %test0% (echo !!Exists!!) else (echo !!Doesn't Exist!!)
(if exist %test0% echo.&echo.&echo -------------------------------------------------&echo.&echo.)>>%test0%
And the file gets created(!)
EDIT: This above was a simplified example, and unfortunately MSalters answer doesn't help me solve the full command (I had hoped it would). The full one line if statement is:
if exist %test0% (echo.&echo.&echo -------------------------------------------------&echo.&echo.) else (set /p .=<nul)>>%test0%&set errorlevel=0||set errorlevel=1
How would I have whichever condition of the if matched output to the file (Hopefully with only one reference to the file, i.e., not one in each if conditional), and have the errorlevel set based on the existance of the file?
Could anyone help with the actual full command issue?
You should never set ERRORLEVEL directly. That name is reserved for reporting on the results of the prior command. When you set the value directly, you override the intended functionality and it ceases to expand to the actual ERRORLEVEL, it expands to the value you set instead. That can break all kinds of code.
You can force the ERRORLEVEL to a value by running a command with known result, redirecting output to nul if necessary: ver >nul sets ERRORLEVEL to 0, set /p .=<nul sets ERRORLEVEL to 1.
You can force the ERRORLEVEL to any particular value of your choosing by using cmd /c exit /b N, where N is an integral value.
You also have faulty logic. Your IF command succeeds (has no error) regardless whether the condition evaluates to TRUE or FALSE. If you want to set the ERRORLEVEL, then you need to do it within your parenthesized blocks.
There is nothing wrong with putting everything on one line, but I find the code easier to read when using multiple lines for complex statements like yours. I believe the following is what you are looking for.
if exist %test0% (
echo.
echo.
echo -------------------------------------------------
echo.
echo.
ver >nul
) >>%test0% else (
set /p .=<nul
)
Edit in response to comments
Not much change needed.
if exist %test0% (
(
echo.
echo.
echo -------------------------------------------------
echo.
echo.
set ERR=0
) >>%test0%
) else (
copy nul %test0%
set ERR=1
)
Check your parentheses. (x) >> output.log redirects the output of x to output.log. That means the redirection happens regardless of what the output is, and in particular always creates the file.
Now if you'd write if Y (echo Text >> output.log) the redirection would be conditional on Y, and might not happen.
[edit]
With the question as it's worded now, the simple solution seems to be:
Set %ERRORLEVEL% based on exist %test0%. No redirection has happened at this point.
Use %ERRORLEVEL% to determine what to do. You can change %test0% without altering %ERRORLEVEL%.
BTW, ERRORLEVEL is not %ERRORLEVEL%
Hey guys, I'm looking for a batch file to tell me if certain folders have been modified today (I'll run it every morning). I'm happy to specify each of the folders to be to be queried, I just haven't been able to find anything that meets my requirements yet. If anyone knows off the top of their head what the code for the .bat would be, that would be awesome :) Thanks in advance.
Here's a batch file that should do the trick:
#echo off
setlocal ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
for /D %%Q IN (*.*) DO (
set FILETIME=%%~tQ
if "!FILETIME:~0,10!"=="%DATE:~4%" echo %%Q
)
This works by comparing the date-part of the file timestamp against the current date.
As written, it checks directories in the current directory, but you could replace *.* with whatever filespec you want to test (or pass it in as an argument).
I don't know if this will work on systems with anything other default English/US regional settings, but it could probably be tweaked to make it work, if it doesn't already. I also don't know what would happen if the system is shared between users in different time-zones.
you can use a vbscript
Set objFS = CreateObject( "Scripting.FileSystemObject" )
strFolder = WScript.Arguments(0)
Set objFolder = objFS.GetFolder(strFolder)
If DateDiff("d", Now, objFolder.DateLastModified ) = 0 Then
WScript.Echo "0"
End If
in your batch file (or command line)
C:\test>cscript //nologo test.vbs myFolderName
use a for loop to catch the output. (Or you can even do everything in vbscript )
I have a set of base filenames, for each name 'f' there are exactly two files, 'f.in' and 'f.out'. I want to write a batch file (in Windows XP) which goes through all the filenames, for each one it should:
Display the base name 'f'
Perform an action on 'f.in'
Perform another action on 'f.out'
I don't have any way to list the set of base filenames, other than to search for *.in (or *.out) for example.
Assuming you have two programs that process the two files, process_in.exe and process_out.exe:
for %%f in (*.in) do (
echo %%~nf
process_in "%%~nf.in"
process_out "%%~nf.out"
)
%%~nf is a substitution modifier, that expands %f to a file name only.
See other modifiers in https://technet.microsoft.com/en-us/library/bb490909.aspx (midway down the page) or just in the next answer.
You can use this line to print the contents of your desktop:
FOR %%I in (C:\windows\desktop\*.*) DO echo %%I
Once you have the %%I variable it's easy to perform a command on it (just replace the word echo with your program)
In addition, substitution of FOR variable references has been enhanced
You can now use the following optional syntax:
%~I - expands %I removing any surrounding quotes (")
%~fI - expands %I to a fully qualified path name
%~dI - expands %I to a drive letter only
%~pI - expands %I to a path only (directory with \)
%~nI - expands %I to a file name only
%~xI - expands %I to a file extension only
%~sI - expanded path contains short names only
%~aI - expands %I to file attributes of file
%~tI - expands %I to date/time of file
%~zI - expands %I to size of file
%~$PATH:I - searches the directories listed in the PATH
environment variable and expands %I to the
fully qualified name of the first one found.
If the environment variable name is not
defined or the file is not found by the
search, then this modifier expands to the
empty string
https://ss64.com/nt/syntax-args.html
In the above examples %I and PATH can be replaced by other valid
values. The %~ syntax is terminated by a valid FOR variable name.
Picking upper case variable names like %I makes it more readable and
avoids confusion with the modifiers, which are not case sensitive.
You can get the full documentation by typing FOR /?
Easiest way, as I see it, is to use a for loop that calls a second batch file for processing, passing that second file the base name.
According to the for /? help, basename can be extracted using the nifty ~n option. So, the base script would read:
for %%f in (*.in) do call process.cmd %%~nf
Then, in process.cmd, assume that %0 contains the base name and act accordingly. For example:
echo The file is %0
copy %0.in %0.out
ren %0.out monkeys_are_cool.txt
There might be a better way to do this in one script, but I've always been a bit hazy on how to pull of multiple commands in a single for loop in a batch file.
EDIT: That's fantastic! I had somehow missed the page in the docs that showed that you could do multi-line blocks in a FOR loop. I am going to go have to go back and rewrite some batch files now...
Expanding on Nathans post. The following will do the job lot in one batch file.
#echo off
if %1.==Sub. goto %2
for %%f in (*.in) do call %0 Sub action %%~nf
goto end
:action
echo The file is %3
copy %3.in %3.out
ren %3.out monkeys_are_cool.txt
:end
There is a tool usually used in MS Servers (as far as I can remember) called forfiles:
The link above contains help as well as a link to the microsoft download page.
The code below filters filenames starting with given substring. It could be changed to fit different needs by working on subfname substring extraction and IF statement:
echo off
rem filter all files not starting with the prefix 'dat'
setlocal enabledelayedexpansion
FOR /R your-folder-fullpath %%F IN (*.*) DO (
set fname=%%~nF
set subfname=!fname:~0,3!
IF NOT "!subfname!" == "dat" echo "%%F"
)
pause
Echoing f.in and f.out will seperate the concept of what to loop and what not to loop when used in a for /f loop.
::Get the files seperated
echo f.in>files_to_pass_through.txt
echo f.out>>files_to_pass_through.txt
for /F %%a in (files_to_pass_through.txt) do (
for /R %%b in (*.*) do (
if "%%a" NEQ "%%b" (
echo %%b>>dont_pass_through_these.txt
)
)
)
::I'm assuming the base name is the whole string "f".
::If I'm right then all the files begin with "f".
::So all you have to do is display "f". right?
::But that would be too easy.
::Let's do this the right way.
for /f %%C in (dont_pass_through_these.txt)
::displays the filename and not the extention
echo %~nC
)
Although you didn't ask, a good way to pass commands into f.in and f.out would be to...
for /F %%D "tokens=*" in (dont_pass_through_these.txt) do (
for /F %%E in (%%D) do (
start /wait %%E
)
)
A link to all the Windows XP commands:link
I apologize if I did not answer this correctly. The question was very hard for me to read.