BATCH- How to put a variable into the move command? - windows

Okay, this is my first question on Stackoverflow, so I'll try to make it a good one.
I've searched all over the web and I couldn't find any information to this. I have created a little batch file that prompts you to put in the name of a file that you would like to move. After that, it asks your your usersname. The problem I'm having is cmd tells me I have incorrect syntax.
Can anyone see what I did wrong?
Below is the code I am using. I just pasted in the part that is having trouble.
Thanks guys!
echo Place the file you wish to move to the Windows Startup Folder on your desktop.
echo When you have placed it there, type in the name of your file, NOT INCLUDING the extension.
echo Example: The file's name is: myfile.bat You type in: myfile
set/p "filename=>"
echo %filename%
echo Next, type in your username.
echo Example: acly6
set/p "USERNAME=>"
echo %USERNAME%
ping 192.2.0.0 -n 1 -w 500 > nul
goto MOVE
:MOVE
echo Moving your file to your startup folder.
move C:\Users\%USERNAME%\Desktop\%filename%.bat
C:\Users\%USERNAME%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\
ping 192.2.0.0 -n 1 -w 1000 > nul
echo Checking Volumes...
ping 192.2.0.0 -n 1 -w 3000 > nul
if EXIST C:\Users\%USERNAME%\AppData\Roaming\Microsoft\Windows\StartMenu\Programs\Startup\%filename%goto COMPLETED
goto FAILED

I editted a bit your script:
Surrounded filepaths with double quotes
Added /y parameter to move command to override automatically the file in new location (if exists)
Spotted some issues:
goto MOVE
:MOVE has no sense as it will continue anyway that path.
goto FAILED GOTO COMPLETED - there're no such labels in your script.
Please shout if you have other problems.
#echo off
echo Place the file you wish to move to the Windows Startup Folder on your desktop.
echo When you have placed it there, type in the name of your file, NOT INCLUDING the extension.
echo Example: The file's name is: myfile.bat You type in: myfile
set/p "filename=>"
echo %filename% echo Next, type in your username.
echo Example: acly6
set/p "USERNAME=>"
echo %USERNAME%
ping 192.2.0.0 -n 1 -w 500 > nul
goto MOVE
:MOVE
echo Moving your file to your startup folder.
move /Y "C:\Users\%USERNAME%\Desktop\%filename%.bat" "C:\Users\%USERNAME%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\"
ping 192.2.0.0 -n 1 -w 1000 > nul
echo Checking Volumes...
ping 192.2.0.0 -n 1 -w 3000 > nul
if EXIST "C:\Users\%USERNAME%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\%filename%" goto COMPLETED
goto FAILED
:FAILED

Related

I can't save cmd comand.bat to file [duplicate]

I am creating a batch file with some simple commands to gather information from a system. The batch file contains commands to get the time, IP information, users, etc.
I assembled all the commands in a batch file, and it runs, but I would like the batch file, when run to output the results to a text file (log). Is there a command that I can add to the batch that would do so?
Keep in mind I do not want to run the batch from cmd, then redirect output ; I want to redirect the output from inside the batch, if that is possible.
The simple naive way that is slow because it opens and positions the file pointer to End-Of-File multiple times.
#echo off
command1 >output.txt
command2 >>output.txt
...
commandN >>output.txt
A better way - easier to write, and faster because the file is opened and positioned only once.
#echo off
>output.txt (
command1
command2
...
commandN
)
Another good and fast way that only opens and positions the file once
#echo off
call :sub >output.txt
exit /b
:sub
command1
command2
...
commandN
Edit 2020-04-17
Every now and then you may want to repeatedly write to two or more files. You might also want different messages on the screen. It is still possible to to do this efficiently by redirecting to undefined handles outside a parenthesized block or subroutine, and then use the & notation to reference the already opened files.
call :sub 9>File1.txt 8>File2.txt
exit /b
:sub
echo Screen message 1
>&9 echo File 1 message 1
>&8 echo File 2 message 1
echo Screen message 2
>&9 echo File 1 message 2
>&8 echo File 2 message 2
exit /b
I chose to use handles 9 and 8 in reverse order because that way is more likely to avoid potential permanent redirection due to a Microsoft redirection implementation design flaw when performing multiple redirections on the same command. It is highly unlikely, but even that approach could expose the bug if you try hard enough. If you stage the redirection than you are guaranteed to avoid the problem.
3>File1.txt ( 4>File2.txt call :sub)
exit /b
:sub
etc.
if you want both out and err streams redirected
dir >> a.txt 2>&1
I know this is an older post, but someone will stumble across it in a Google search and it also looks like some questions the OP asked in comments weren't specifically addressed. Also, please go easy on me since this is my first answer posted on SO. :)
To redirect the output to a file using a dynamically generated file name, my go-to (read: quick & dirty) approach is the second solution offered by #dbenham. So for example, this:
#echo off
> filename_prefix-%DATE:~-4%-%DATE:~4,2%-%DATE:~7,2%_%time:~0,2%%time:~3,2%%time:~6,2%.log (
echo Your Name Here
echo Beginning Date/Time: %DATE:~-4%-%DATE:~4,2%-%DATE:~7,2%_%time:~0,2%%time:~3,2%%time:~6,2%.log
REM do some stuff here
echo Your Name Here
echo Ending Date/Time: %DATE:~-4%-%DATE:~4,2%-%DATE:~7,2%_%time:~0,2%%time:~3,2%%time:~6,2%.log
)
Will create a file like what you see in this screenshot of the file in the target directory
That will contain this output:
Your Name Here
Beginning Date/Time: 2016-09-16_141048.log
Your Name Here
Ending Date/Time: 2016-09-16_141048.log
Also keep in mind that this solution is locale-dependent, so be careful how/when you use it.
echo some output >"your logfile"
or
(
echo some output
echo more output
)>"Your logfile"
should fill the bill.
If you want to APPEND the output, use >> instead of >. > will start a new logfile.
#echo off
>output.txt (
echo Checking your system infor, Please wating...
systeminfo | findstr /c:"Host Name"
systeminfo | findstr /c:"Domain"
ipconfig /all | find "Physical Address"
ipconfig | find "IPv4"
ipconfig | find "Default Gateway"
)
#pause
Add these two lines near the top of your batch file, all stdout and stderr after will be redirected to log.txt:
if not "%1"=="STDOUT_TO_FILE" %0 STDOUT_TO_FILE %* >log.txt 2>&1
shift /1
There is a cool little program you can use to redirect the output to a file and the console
some_command ^| TEE.BAT [ -a ] filename
#ECHO OFF
:: Check Windows version
IF NOT "%OS%"=="Windows_NT" GOTO Syntax
:: Keep variables local
SETLOCAL
:: Check command line arguments
SET Append=0
IF /I [%1]==[-a] (
SET Append=1
SHIFT
)
IF [%1]==[] GOTO Syntax
IF NOT [%2]==[] GOTO Syntax
:: Test for invalid wildcards
SET Counter=0
FOR /F %%A IN ('DIR /A /B %1 2^>NUL') DO CALL :Count "%%~fA"
IF %Counter% GTR 1 (
SET Counter=
GOTO Syntax
)
:: A valid filename seems to have been specified
SET File=%1
:: Check if a directory with the specified name exists
DIR /AD %File% >NUL 2>NUL
IF NOT ERRORLEVEL 1 (
SET File=
GOTO Syntax
)
:: Specify /Y switch for Windows 2000 / XP COPY command
SET Y=
VER | FIND "Windows NT" > NUL
IF ERRORLEVEL 1 SET Y=/Y
:: Flush existing file or create new one if -a wasn't specified
IF %Append%==0 (COPY %Y% NUL %File% > NUL 2>&1)
:: Actual TEE
FOR /F "tokens=1* delims=]" %%A IN ('FIND /N /V ""') DO (
> CON ECHO.%%B
>> %File% ECHO.%%B
)
:: Done
ENDLOCAL
GOTO:EOF
:Count
SET /A Counter += 1
SET File=%1
GOTO:EOF
:Syntax
ECHO.
ECHO Tee.bat, Version 2.11a for Windows NT 4 / 2000 / XP
ECHO Display text on screen and redirect it to a file simultaneously
ECHO.
IF NOT "%OS%"=="Windows_NT" ECHO Usage: some_command ³ TEE.BAT [ -a ] filename
IF NOT "%OS%"=="Windows_NT" GOTO Skip
ECHO Usage: some_command ^| TEE.BAT [ -a ] filename
:Skip
ECHO.
ECHO Where: "some_command" is the command whose output should be redirected
ECHO "filename" is the file the output should be redirected to
ECHO -a appends the output of the command to the file,
ECHO rather than overwriting the file
ECHO.
ECHO Written by Rob van der Woude
ECHO http://www.robvanderwoude.com
ECHO Modified by Kees Couprie
ECHO http://kees.couprie.org
ECHO and Andrew Cameron
#echo OFF
[your command] >> [Your log file name].txt
I used the command above in my batch file and it works. In the log file, it shows the results of my command.
Adding the following lines at the bottom of your batch file will grab everything just as displayed inside the CMD window and export into a text file:
powershell -c "$wshell = New-Object -ComObject wscript.shell; $wshell.SendKeys('^a')
powershell -c "$wshell = New-Object -ComObject wscript.shell; $wshell.SendKeys('^c')
powershell Get-Clipboard > MyLog.txt
It basically performs a select all -> copy into clipboard -> paste into text file.
This may fail in the case of "toxic" characters in the input.
Considering an input like thisIsAnIn^^^^put is a good way how to get understand what is going on.
Sure there is a rule that an input string MUST be inside double quoted marks but I have a feeling that this rule is a valid rule only if the meaning of the input is a location on a NTFS partition (maybe it is a rule for URLs I am not sure).
But it is not a rule for an arbitrary input string of course (it is "a good practice" but you cannot count with it).

Window batch commands to detect if downloaded file exists?

I use a windows batch file that scans download folder and if it detects label.pdf it sends to local printer. This works fine most of the time but often it detects file before the file completely downloads which causes PDFtoPrinter error. Is there a way to make sure the download process is complete before attempting to detect?
#echo off
cls
:start
IF EXIST "C:\Users\Downloads\label.pdf" (
echo "Found!"
ping 127.0.0.1 -n 1 -w 3000> nul
"C:\Users\Downloads\PDFtoPrinter" label.pdf "4BARCODE 4B-2054A"
ping 127.0.0.1 -n 1 -w 10000> nul
del "C:\Users\Downloads\label.pdf"
) ELSE (
echo "it isn't here!"
)
goto start
You can use the mechanism to check if a file is locked for exclusive access by another application.
#echo off
cls
:start
IF EXIST "C:\Users\Downloads\label.pdf" (
REM check if file is locked
2>nul (>>"C:\Users\Downloads\label.pdf" (call )) && ("C:\Users\Downloads\PDFtoPrinter" label.pdf "4BARCODE 4B-2054A") || (echo file is locked)
) ELSE (
echo "it isn't here!"
)
Timeout /T 10
goto start

Issue concerning path input in .bat menu

Hi I am trying to make a small menu in which the .bat file uses the user input to define a path. The code below works.
#ECHO OFF
SET /P var= Type The FULL Path In Here:
MKDIR %var%\
pause
However when I try to implement the code into the menu below. It fails and I can't read the error because it immediately exits the batch file. I am running a windows 10 machine and running the batch from the C:\ drive. The batch file makes the folders on the C:\ drive as well. I would be grateful for any help Thanks.
ECHO OFF
CLS
:MENU
ECHO.
ECHO ...............................................
ECHO PRESS 1 to select your task, or 2 TO EXIT.
ECHO ...............................................
ECHO.
ECHO 1 - Set Path
ECHO.
ECHO 2 - EXIT
ECHO.
SET /P M=Type 1 or 5 then press ENTER:
IF %M%==1 GOTO CallScript1
IF %M%==5 GOTO EOF
CallScript1
#ECHO OFF
SET /P var= Type The FULL Path In Here:
MKDIR %var%\
GOTO:EOF
You are missing the colon before the label CallScript1 on line 17
i.e. replace
CallScript1
with
:CallScript1

Redirecting Output from within Batch file

I am creating a batch file with some simple commands to gather information from a system. The batch file contains commands to get the time, IP information, users, etc.
I assembled all the commands in a batch file, and it runs, but I would like the batch file, when run to output the results to a text file (log). Is there a command that I can add to the batch that would do so?
Keep in mind I do not want to run the batch from cmd, then redirect output ; I want to redirect the output from inside the batch, if that is possible.
The simple naive way that is slow because it opens and positions the file pointer to End-Of-File multiple times.
#echo off
command1 >output.txt
command2 >>output.txt
...
commandN >>output.txt
A better way - easier to write, and faster because the file is opened and positioned only once.
#echo off
>output.txt (
command1
command2
...
commandN
)
Another good and fast way that only opens and positions the file once
#echo off
call :sub >output.txt
exit /b
:sub
command1
command2
...
commandN
Edit 2020-04-17
Every now and then you may want to repeatedly write to two or more files. You might also want different messages on the screen. It is still possible to to do this efficiently by redirecting to undefined handles outside a parenthesized block or subroutine, and then use the & notation to reference the already opened files.
call :sub 9>File1.txt 8>File2.txt
exit /b
:sub
echo Screen message 1
>&9 echo File 1 message 1
>&8 echo File 2 message 1
echo Screen message 2
>&9 echo File 1 message 2
>&8 echo File 2 message 2
exit /b
I chose to use handles 9 and 8 in reverse order because that way is more likely to avoid potential permanent redirection due to a Microsoft redirection implementation design flaw when performing multiple redirections on the same command. It is highly unlikely, but even that approach could expose the bug if you try hard enough. If you stage the redirection than you are guaranteed to avoid the problem.
3>File1.txt ( 4>File2.txt call :sub)
exit /b
:sub
etc.
if you want both out and err streams redirected
dir >> a.txt 2>&1
I know this is an older post, but someone will stumble across it in a Google search and it also looks like some questions the OP asked in comments weren't specifically addressed. Also, please go easy on me since this is my first answer posted on SO. :)
To redirect the output to a file using a dynamically generated file name, my go-to (read: quick & dirty) approach is the second solution offered by #dbenham. So for example, this:
#echo off
> filename_prefix-%DATE:~-4%-%DATE:~4,2%-%DATE:~7,2%_%time:~0,2%%time:~3,2%%time:~6,2%.log (
echo Your Name Here
echo Beginning Date/Time: %DATE:~-4%-%DATE:~4,2%-%DATE:~7,2%_%time:~0,2%%time:~3,2%%time:~6,2%.log
REM do some stuff here
echo Your Name Here
echo Ending Date/Time: %DATE:~-4%-%DATE:~4,2%-%DATE:~7,2%_%time:~0,2%%time:~3,2%%time:~6,2%.log
)
Will create a file like what you see in this screenshot of the file in the target directory
That will contain this output:
Your Name Here
Beginning Date/Time: 2016-09-16_141048.log
Your Name Here
Ending Date/Time: 2016-09-16_141048.log
Also keep in mind that this solution is locale-dependent, so be careful how/when you use it.
#echo off
>output.txt (
echo Checking your system infor, Please wating...
systeminfo | findstr /c:"Host Name"
systeminfo | findstr /c:"Domain"
ipconfig /all | find "Physical Address"
ipconfig | find "IPv4"
ipconfig | find "Default Gateway"
)
#pause
echo some output >"your logfile"
or
(
echo some output
echo more output
)>"Your logfile"
should fill the bill.
If you want to APPEND the output, use >> instead of >. > will start a new logfile.
Add these two lines near the top of your batch file, all stdout and stderr after will be redirected to log.txt:
if not "%1"=="STDOUT_TO_FILE" %0 STDOUT_TO_FILE %* >log.txt 2>&1
shift /1
There is a cool little program you can use to redirect the output to a file and the console
some_command ^| TEE.BAT [ -a ] filename
#ECHO OFF
:: Check Windows version
IF NOT "%OS%"=="Windows_NT" GOTO Syntax
:: Keep variables local
SETLOCAL
:: Check command line arguments
SET Append=0
IF /I [%1]==[-a] (
SET Append=1
SHIFT
)
IF [%1]==[] GOTO Syntax
IF NOT [%2]==[] GOTO Syntax
:: Test for invalid wildcards
SET Counter=0
FOR /F %%A IN ('DIR /A /B %1 2^>NUL') DO CALL :Count "%%~fA"
IF %Counter% GTR 1 (
SET Counter=
GOTO Syntax
)
:: A valid filename seems to have been specified
SET File=%1
:: Check if a directory with the specified name exists
DIR /AD %File% >NUL 2>NUL
IF NOT ERRORLEVEL 1 (
SET File=
GOTO Syntax
)
:: Specify /Y switch for Windows 2000 / XP COPY command
SET Y=
VER | FIND "Windows NT" > NUL
IF ERRORLEVEL 1 SET Y=/Y
:: Flush existing file or create new one if -a wasn't specified
IF %Append%==0 (COPY %Y% NUL %File% > NUL 2>&1)
:: Actual TEE
FOR /F "tokens=1* delims=]" %%A IN ('FIND /N /V ""') DO (
> CON ECHO.%%B
>> %File% ECHO.%%B
)
:: Done
ENDLOCAL
GOTO:EOF
:Count
SET /A Counter += 1
SET File=%1
GOTO:EOF
:Syntax
ECHO.
ECHO Tee.bat, Version 2.11a for Windows NT 4 / 2000 / XP
ECHO Display text on screen and redirect it to a file simultaneously
ECHO.
IF NOT "%OS%"=="Windows_NT" ECHO Usage: some_command ³ TEE.BAT [ -a ] filename
IF NOT "%OS%"=="Windows_NT" GOTO Skip
ECHO Usage: some_command ^| TEE.BAT [ -a ] filename
:Skip
ECHO.
ECHO Where: "some_command" is the command whose output should be redirected
ECHO "filename" is the file the output should be redirected to
ECHO -a appends the output of the command to the file,
ECHO rather than overwriting the file
ECHO.
ECHO Written by Rob van der Woude
ECHO http://www.robvanderwoude.com
ECHO Modified by Kees Couprie
ECHO http://kees.couprie.org
ECHO and Andrew Cameron
#echo OFF
[your command] >> [Your log file name].txt
I used the command above in my batch file and it works. In the log file, it shows the results of my command.
Adding the following lines at the bottom of your batch file will grab everything just as displayed inside the CMD window and export into a text file:
powershell -c "$wshell = New-Object -ComObject wscript.shell; $wshell.SendKeys('^a')
powershell -c "$wshell = New-Object -ComObject wscript.shell; $wshell.SendKeys('^c')
powershell Get-Clipboard > MyLog.txt
It basically performs a select all -> copy into clipboard -> paste into text file.
This may fail in the case of "toxic" characters in the input.
Considering an input like thisIsAnIn^^^^put is a good way how to get understand what is going on.
Sure there is a rule that an input string MUST be inside double quoted marks but I have a feeling that this rule is a valid rule only if the meaning of the input is a location on a NTFS partition (maybe it is a rule for URLs I am not sure).
But it is not a rule for an arbitrary input string of course (it is "a good practice" but you cannot count with it).

Bat file and labels

I am trying to write a bat file for a network policy that will install a program if it doesn't exist as well as several other functions. I am using GOTO statements depending on whether or not certain criterion are met. However, it seems that the labels are not firing correctly as all of them do.
I have simplified my script so as to grasp some idea of what may be happening.
#echo off
IF EXIST c:\test\test.txt (GOTO :EXISTING) ELSE GOTO :MISSING
:EXISTING
echo file exists
:MISSING
echo file missing
ping localhost -n 5 >NUL
Basically it checks to see that the file "test.txt" exists in folder "c:\test" which id does. So it should echo file exists to the console. However, both "file exists" and "file missing" are echoed to the console. I find that if I remove the file from the folder or simply rename it, it only echoes "file missing"
Why is it running running both labels?
Because a GOTO is just a jump in execution to a point in the script, then execution continues sequentially from that point. If you want it to stop after running 'EXISTING', then you need to do something like this. Note the extra GOTO and new label:
#ECHO OFF
IF EXIST c:\test\test.txt (GOTO :EXISTING) ELSE GOTO :MISSING
:EXISTING
echo file exists
goto :NEXTBIT
:MISSING
echo file missing
:NEXTBIT
ping localhost -n 5 >NUL
It's worth noting though that with cmd.exe (i.e., the NT-based command shells [NT, Win2k, XP, etc]), you can do IF...ELSE blocks like this:
#ECHO OFF
IF EXIST c:\test\test.txt (
ECHO File exists
) ELSE (
ECHO File missing
)
ping localhost -n 5 >nul
...so you can eliminate your GOTOs entirely.
It's because you need to skip over the "missing" bit if it exists:
#echo off
IF EXIST c:\test\test.txt (GOTO :EXISTING) ELSE GOTO :MISSING
:EXISTING
echo file exists
goto :COMMON
:MISSING
echo file missing
:COMMON
ping localhost -n 5 >NUL
You may also want to keep in mind that the current cmd.exe batch language is a fair bit more powerful than that which came with MS-DOS. I would prefer this one:
#echo off
if exist c:\test\test.txt (
echo file exists
) else (
echo file missing
)
ping localhost -n 5 >nul
After you echo file exists the next command is
echo file missing
You need to do something to skip the missing case. Perhaps another goto to a :PING label?
When you're debugging it helps to keep the echo on.
Because GOTO statement moves the execution to that label. To use it in the situation like yours, you need to add another GOTO label.
#echo off
IF EXIST c:\test\test.txt (GOTO :EXISTING) ELSE GOTO MISSING
:EXISTING
echo file exists
GOTO END
:MISSING
echo file missing
GOTO END
:END
ping localhost -n 5 >NUL
#echo off
IF EXIST "c:\test\test.txt" ( :: warning double quotes
GOTO EXISTING
) ELSE ( :: this format best in batch
GOTO MISSING
) :: don't forget
:EXISTING
echo file exists
goto OTHER :: if file exist jump OTHER
:MISSING
echo file missing
:: label is not required
:OTHER
timeout /t 5 >nul
pause

Resources