What I am trying to do is a backup by cmd commands but the problem is when I am taking the USB backup to another PC to back up the drive names are different.
For example when I do:
XCOPY G:\*.BMP X:\ /h/i/c/k/e/y/r/d
In the other computer the drives will not be G and X.
What I am seeking to do is if it is possible to make a program that I can enter with the keyboard what drive I want to backup and to what drive.
For example:
XCOPY "driver name keyboard input":\*.BMP "driver name keyboard input":/" /h/i/c/k/e/y/r/d
Yes, it can be done using a PowerShell or batch-file script (cmd tag seems to imply Windows OS).
Let's choose the latter. Next batch-file code snippet would do the same as the command in question: XCOPY G:*.BMP X:\ /h/i/c/k/e/y/r/d:
set "DriveIn=G"
set "DriveOu=X"
XCOPY %DriveIn%:*.BMP %DriveOu%:\ /h/i/c/k/e/y/r/d
Instead of hard-coded DriveIn and DriveOu, you can prompt for user input:
set /P "DriveIn=please choose SOURCE drive letter "
set /P "DriveOu=please choose TARGET drive letter "
XCOPY %DriveIn%:*.BMP %DriveOu%:\ /h/i/c/k/e/y/r/d
Hints for (necessary!) validity checks:
:dfromscratch
set "DriveIn="
set "DriveOu="
:dsource
set /P "DriveIn=please choose SOURCE drive letter "
rem basic validity check
if not defined DriveIn goto :dsource
if not exist "%DriveIn%:\" goto :dsource
:dtarget
set /P "DriveOu=please choose TARGET drive letter "
rem basic validity check
if not defined DriveOu goto :dtarget
if not exist "%DriveOu%:\" goto :dtarget
if /I "%DriveIn%"=="%DriveOu%" goto :dfromscratch
rem involve more validity check here!!!
XCOPY %DriveIn%:*.BMP %DriveOu%:\ /h/i/c/k/e/y/r/d
Some hints for (more) validity checks.
To show available disk drives:
wmic logicaldisk get Description, DeviceID, DriveType, FileSystem, VolumeName
To get a list of available disk drives, use for /F loop (note %%G in a batch script):
for /F %%G in ('
wmic logicaldisk where "DriveType != 5" get DeviceID^, DriveType^|find ":"
') do echo %%G
or next oneliner (note %G in cmd): copy&paste into an open cmd window:
for /F %G in ('wmic logicaldisk where "DriveType != 5" get DeviceID^, DriveType^|find ":"') do #echo %G
Another approach (only a draft, needs more elaboration): build a list of available drive letters %drives% and use choice command instead of set /P:
set "drives=GX"
choice /C %drives% /M "Select SOURCE drive letter"
Related
I'm working on an unattended automated install of SQL 2008, 2012 and 2014 which so far is working with my batch command. The one issue I'm encountering is that in order to use a core function found in each program (management studio) properly on Windows 10, it needs to run as an admin.
In Windows 10 this can be done manually by opening the file location of the program shortcut - right click - properties - "compatibility" tab - "change settings for all users" - check the box "run this program as an administrator". Is there a way to have a batch command check that box? This way staff won't need to manually run it as an admin each time, it'll just open Management Studio automatically as an admin.
My batch command can be found below to automate the install. The beginning finds the installation files, sets the sa password to whatever I want and pulls the custom settings for the SQL installer from the configurationfile.ini file. I need the "run as an admin" for all users to run after all that.
start "" "%~dp0SQL2008\setup.exe" /SAPWD="XXXXXXXX" /ConfigurationFile="ConfigurationFile.ini" /quiet
#echo off
setlocal
call :reg_compat "C:\User\Test\test.exe" "WINXPSP3 RUNASADMIN"
if errorlevel 1 echo Registry write failed.
exit /b
:reg_compat fullpath, reg_data
setlocal
set "reg_key=HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers"
set "reg_data="
:: Get current registry data.
for /f "tokens=1,2*" %%A in ('2^>nul reg query "%reg_key%" /v "%~1"') do (
if /i "%%~A" == "%~1" set "reg_data=%%~C"
)
:: Write new entry and exit.
if not defined reg_data (
>nul reg add "%reg_key%" /v "%~1" /d "%~2" /f
if errorlevel 1 exit /b 1
exit /b 0
)
:: Copy original registry data.
set "reg_data_original=%reg_data%"
:: Append new data if not in original registry data.
for %%A in (%~2) do (
set "value_exist="
for %%B in (%reg_data_original%) do (
if "%%~A" == "%%~B" set "value_exist=1"
)
if not defined value_exist (
call set "reg_data=%%reg_data%% %%~A"
)
)
:: Continue only if registry data is modified.
if "%reg_data_original%" == "%reg_data%" exit /b 0
:: Write modified entry and exit.
>nul reg add "%reg_key%" /v "%~1" /d "%reg_data%" /f
if errorlevel 1 exit /b 2
exit /b 0
The code is set to write a test entry. The test entry will add
Windows XP SP3 and Run As Admin compatibility for that filepath.
For actual use change the arguments to call the label :reg_compat
with the fullpath to the file as the 1st argument and the
reg_data compatibility arguments as the 2nd argument. The
compatibility arguments are uppercase and separated with a space.
The label :reg_compat will write new entries or update entries with
adding new compatibility arguments. The errorlevel from the called
label is set to not 0 if reg add fails.
Minimal code instead if you need just that:
#echo off
setlocal
set "reg_key=HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers"
reg add "%reg_key%" /v "C:\User\Test\test.exe" /d "WINXPSP3 RUNASADMIN" /f
I'm in need of a batch command that will look into a directory's sub folders and find a partial file name. If that file exists, then move that directory otherwise leave it alone.
I have a folder full of movies:
D:\Movies\movie1\
\movie2\
\movie3\
Within each movie folder I would like to know if it has a trailer downloaded into the folder, if so then move that directory to x:\movies. I say partial file name as every trailer file will include the title of the movie with "-trailer" added to the end (f.e. The Interview (2014)-trailer).
Let's look for a solution from Windows CLI (Command Line Interpreter) with -> prompt using An A-Z Index of the Windows CMD command line and with next scenario:
->tree d:\test\movies
D:\TEST\MOVIES
├───movie1
├───movie2
├───movie3
└───movie4
->tree d:\test\xmovies
D:\TEST\XMOVIES
No subfolders exist
->dir /B /S /A-D "d:\test\movies"
d:\test\movies\movie1\The View (2014)-trailer missing.rtf
d:\test\movies\movie2\The Interview (2014)-trailer.bat
d:\test\movies\movie2\The Interview (2014)-trailer.bmp
d:\test\movies\movie2\The Interview (2014)-trailer.txt
d:\test\movies\movie3\An Interview (2014)-trailer.bmp
To find all those files under MOVIES subfolder with -trailer added to the filename end preceding . of file extension:
->dir /B /S /A-D "d:\test\movies\*-trailer.*"
d:\test\movies\movie2\The Interview (2014)-trailer.bat
d:\test\movies\movie2\The Interview (2014)-trailer.bmp
d:\test\movies\movie2\The Interview (2014)-trailer.txt
d:\test\movies\movie3\An Interview (2014)-trailer.bmp
To get folder names only:
->for /F "tokens=*" %G in ('dir /B /S /A-D "d:\test\movies\*-trailer.*"') do #echo %~dpG
d:\test\Movies\movie2\
d:\test\Movies\movie2\
d:\test\Movies\movie2\
d:\test\Movies\movie3\
But here the movie2 appears more than once! And, moreover, the move command does not allow source directory with trailing backslash:
->move "D:\test\Movies\movie4\" "D:\test\xMovies\"
The system cannot find the file specified.
->move "D:\test\Movies\movie4" "D:\test\xMovies\"
1 dir(s) moved.
Therefore we need switch from Windows shell (CLI) to batch scripting. Create file 28167824.bat (e.g with notepad and save it to D:\bat\StackOverflow folder):
#ECHO OFF >NUL
#SETLOCAL enableextensions disabledelayedexpansion
for /F "tokens=*" %%G in (
'dir /B /S /A-D "d:\test\movies\*-trailer.*"'
) do (
set "rawfolder=%%~dpG"
if exist "%%~dpG" call :moveDir
)
:endlocal
#ENDLOCAL
goto :eof
:moveDir
set "srcfolder=%rawfolder:~0,-1%"
`enter code here`echo move "%srcfolder%" "d:\test\xMovies\"
rem move "%srcfolder%" "d:\test\xMovies\"
goto :eof
Run this batch script, the template of next move commands is the same as in that successful move command mentioned above:
->D:\bat\StackOverflow\28167824
move "d:\test\Movies\movie2" "d:\test\xMovies\"
move "d:\test\Movies\movie2" "d:\test\xMovies\"
move "d:\test\Movies\movie2" "d:\test\xMovies\"
move "d:\test\Movies\movie3" "d:\test\xMovies\"
Bingo! Now we could remove rem before move "%srcfolder%" "d:\test\xMovies\", save the script and run it:
->D:\bat\StackOverflow\28167824
move "d:\test\Movies\movie2" "d:\test\xMovies\"
1 dir(s) moved.
move "d:\test\Movies\movie3" "d:\test\xMovies\"
1 dir(s) moved.
And here is final configuration, cf. starting scenario:
->tree d:\test\movies
D:\TEST\MOVIES
└───movie1
->tree d:\test\xmovies
D:\TEST\XMOVIES
├───movie2
├───movie3
└───movie4
I have this really nice line in my batch file that tells me how many lines are in a file:
find /v /c "" C:\Users\c1921\mypath\myfolder\!$Unit!.txt
This is nice and gives me 31 for the particular file I'm working with. My problem is the file looks something like this:
Microsoft (R) Windows Script Host Version 5.8
Copyright (C) Microsoft Corporation. All rights reserved.
my_handled
219278
check
219276
control
219274
I want to be able to skip the first three lines entirely and then save the first value and then use the second value in my next command etc.
How do I save the number (e.g. 31) into a variable in my batch file?
On a hunch I tried setting a variable like so but it wasn't effective:
set "$testVar="""
echo !$testVar!
This command allows you to "save the number (e.g. 31) into a variable in my batch file":
for /F %%a in ('find /v /c "" ^< C:\Users\c1921\mypath\myfolder\!$Unit!.txt') do set numLines=%%a
This command allows you "to skip the first three lines entirely" and process the rest:
for /F "skip=3 delims=" %%a in (C:\Users\c1921\mypath\myfolder\!$Unit!.txt) do echo Processing: "%%a"
However, in my opinion this problem could be entirely avoided if the three first lines in the text file are supressed from the very beginning. I think this file is generated via a VBScript of JScript program that is executed this way:
cscript progname.vbs > C:\Users\c1921\mypath\myfolder\!$Unit!.txt
The first three lines in the text file may be avoided adding //nologo switch this way:
cscript //nologo progname.vbs > C:\Users\c1921\mypath\myfolder\!$Unit!.txt
#ECHO OFF
SETLOCAL
SET /a count=3
SET "first="
FOR /f "skip=3delims=" %%a IN (q25089468.txt) DO (
IF DEFINED first (CALL :show %%a) ELSE (SET "first=%%a")
)
ECHO count=%count%
GOTO :EOF
:show
ECHO first=%first% second=%1
SET /a count+=2
SET "first="
GOTO :eof
I used a file named q25089468.txt containing your data for my testing.
You appear to be asking two entirely different things - how to count the lines and how to skip the first 3, then deliver each succeeding pair to another process.
I've encountered a bit of an issue in a Batch script I am making.
In this script, I want to it react to my pressing a button the moment I press it, and 'set'ting a new variable without having to press Enter.
Currently, it's like this;
set b=
set /p b=
ig %b%==a (
goto Success
)
It allows me to press the button I want, however I don't want it to wait until I press Enter afterwards.
For VISTA and later
If you know your script will run on Vista or later (not XP), then you can use the choice command. You must specify which characters to accept. By default, CHOICE is case insensitive. The returned ERRORLEVEL corresponds to the position of the selected letter within the choice list.
For example, to wait for the user to press A, B, or C (case sensitive) and store the key value in a variable:
setlocal enableDelayedExpansion
set "list=ABC"
choice /cs /c "%list%"
set "list=.%list%"
set "key=!list:~%errorlevel%,1!"
echo %key%
Full documentation is available from the command line by typing HELP CHOICE or CHOICE /?
For all modern Windows, including XP
I was introduced to a very clever solution that works on XP and beyond when I was developing my batch implementation of the SNAKE game. This solution allows you to capture nearly any key press.
set "key="
for /F "usebackq delims=" %%A in (`xcopy /w "%~f0" "%~f0" 2^>NUL`) do (
if not defined key set "key=%%A"
)
set "key=%key:~-1%"
set key
use choice in batch
choice /c YN /m "Is Yes"
if ( %ERRORLEVEL% == 1 ) (
ECHO "SUCCESS"
)
I would like to run a script where I can get the windows Name and version of the system of all computers running in the company, put it in a text fil. Then make a system variable out of my windows name . I know what to run but where I am running into an issue is a place holder. so here is my code:
:OS_NAME
Set OS_NAME= systeminfo | find "OS Name"
:OS_Ver
Set OS_Version= systeminfo | findstr /B /C:"OS Version"
systeminfo | findstr /B /C:"OS Name" /C:"OS Version" /c:"BIOS Version" | >> G:\Directory\%Computername%
:OS_Arch
IF exist "%programfiles(x86)% (SET OS_ARCH=X64)
Else (SET OS_ARCH=X86)
:Win_7
systeminfo | find "Microsoft Windows 7" > nul
if %ERRORLEVEL% == 0 (
goto ver_7)
:Ver_7
Set Win7= systeminfo | find "Microsoft Windows 7"
Echo %computername% is running %WIN7% in %OS_ARCH% Environment >> G:\Directory\Win7Comps.txt
So basically I would like a place holder for the results of Systeminfo which i can refer to and parse it my SET command when I am making my system variables.
Thanks, any help would be appreaciated.
Not exactly sure what you're looking for, but the biggest problem I see is that systeminfo takes forever to run and returns much more information than you're looking for. You'd be better off capturing wmi queries using wmic. This is basically a rewrite of your example script, just using wmic rather than systeminfo. It should be much, much faster.
#echo off
setlocal
set prefix=G:\Directory
for /f "usebackq tokens=1,2 delims==|" %%I in (`wmic os get name^,version /format:list`) do 2>NUL set "%%I=%%J"
for /f "tokens=2 delims==" %%I in ('wmic bios get version /format:list') do set "bios=%%I"
for /f "tokens=2 delims==" %%I in ('wmic computersystem get model /format:list') do set "model=%%I"
>>"%prefix%\%COMPUTERNAME%" echo OS Name: %name%
>>"%prefix%\%COMPUTERNAME%" echo OS Version: %version%
>>"%prefix%\%COMPUTERNAME%" echo PC Model: %model%
>>"%prefix%\%COMPUTERNAME%" echo BIOS Version: %bios%
if defined PROGRAMFILES(x86) (set arch=X64) else set arch=X86
if "%name%" neq "%name:Windows 8=%" (
set out=%prefix%\Win8Comps.txt
) else if "%name%" neq "%name:Windows 7=%" (
set out=%prefix%\Win7Comps.txt
) else if "%name%" neq "%name:Windows Vista=%" (
set out=%prefix%\WinVistaComps.txt
) else if "%name%" neq "%name:Windows XP=%" (
set out=%prefix%\WinXPComps.txt
)
>>"%out%" echo %COMPUTERNAME% is running %name% in %arch% environment
Type wmic /? for more info, and try wmic computersystem get /? or similar to see a list of items that can be queried under each class.
wmic is the Swiss Army knife of Windows. Fun fact: you can even use wmic to generate a web page table of installed software on a remote system.
You are giving batch a little too much credit. If you ran echo %OS_NAME% it would literally echo systeminfo | find "OS Name". Variables in batch will always just expand, it won't process any further. This will also more than likely try to run find "OS Name" when you try to set the variable as the | is not escaped nor enclosed in double quotes.
If you want to set the output of a command to a value you have to capture it in a for statement like this:
for /f "tokens=2 delims=:" %%a in ('systeminfo ^| find "OS Name"') do set OS_Name=%%a
Then remove the leading spaces like this: (there is probably a better way to do this)
for /f "tokens=* delims= " %%a in ("%OS_Name%") do set OS_Name=%%a
A few things to note here. 1.) "tokens=2 delims=:" is setting the delimiter to : and it is selecting the second section only, which will pull only the part you want. 2.) the | is escaped with a ^, this needs to be done in for loops or anything after that will attempt to execute as seperate commands. 3.) "tokens=* delims= " The token here is * which is all tokens.
A few other problems I found.
systeminfo | findstr /B /C:"OS Name" /C:"OS Version" /c:"BIOS Version" | >> G:\Directory\%Computername%
This has an extra | character at the end.
IF exist "%programfiles(x86)% (SET OS_ARCH=X64)
Else (SET OS_ARCH=X86)
Two problems here, you didn't finish the double quote around the path, and else has to be on the same line as the ending parentheses of the if statement, like this:
IF exist "%programfiles(x86)% (SET OS_ARCH=X64
) Else (SET OS_ARCH=X86)
Otherwise it tries to process else as it's own command