batch script, renaming a xml file inside a folder - batch-file

I am writing a batch file whereby I can rename a xml file name inside a folder on my Desktop.
prompt the user to key in the file name
if the file name is found, it will then prompt the user to key in an existing xml file name
if an existing xml file name, it will then prompt the user to key in a new xml file name
an overview of my contents inside a file name(bb).
this is my batch-script
#echo off
set /p fn=Enter Folder name:
if exist C:\Users\roberts\Desktop\%fn% (
set /p oldxmlname=Enter a old xml file name:
if exist C:\Users\roberts\Desktop\%fn%\%oldxmlname%.xml (
set /p newxmlname=Enter a new xml file name:
ren C:\Users\roberts\Desktop\%oldxmlname%.xml %newxmlname%.xml
echo file name changed successfully.
)
)else (
echo folder not found in path.
echo C:\Users\roberts\Desktop\%fn%
)
this is my output. The file name didn't change at all.

Within a block statement (a parenthesised series of statements), the entire block is parsed and then executed. Any %var% within the block will be replaced by that variable's value at the time the block is parsed - before the block is executed.
Hence, IF (something) else (somethingelse) will be executed using the values of %variables% at the time the IF is encountered. The same comment goes for the REN.
Two common ways to overcome this are 1) to use setlocal enabledelayedexpansion and use !var! in place of %var% to access the changed value of var or 2) to call a subroutine to perform further processing using the changed values.
And if an ELSE clause is used, the IF-true command must be (parenthesised), and the ) and ELSE must be on the same physical line. If ELSE-true command is (parenthesised), the ELSE and ( must be on the same physical line. There must be a Space either side of the else keyword.
A demonstration:
#echo off
SETLOCAL
cls
set var=ORIGINAL
echo Start value of var=%var%
for %%i in (1) do (SET var=AFTER
ECHO var is %var% in the for loop
)
echo Final value of var=%var%
ENDLOCAL
ECHO.
echo ---- try again with ENABLEDELAYEDEXPANSION
ECHO.
setlocal enabledelayedexpansion
set var=ORIGINAL
echo Start value of var=%var%
for %%i in (1) do (SET var=AFTER
ECHO var is %var% not !var! in the for loop
ECHO Note: in the loop VAR has old value %var% and new value !var!
)
echo Final value of var=%var%
endlocal
Note how the value of var is interpreted differently depending on the use of setlocal or setlocal enabledelayedexpansion. The !var! syntax is only available in delayedexpansion mode and accesses the value of var as it is modified in the block,

You left \%fn% out of the ren command, so the file you're asking to rename really doesn't exist.
You want ren C:\Users\roberts\Desktop\%fn%\%oldxmlname%.xml %newxmlname%.xml

Here is a method that doesn't need delayed expansion, which your code does.
When changing a variable and using it within a loop, then delayed expansion is required.
There are some quotes to protect long file/path elements and an added backslash to detect a path and not a file.
#echo off
set /p fn=Enter Folder name:
if not exist "C:\Users\roberts\Desktop\%fn%\" (
echo The engines canna take the strain captain, try again!
goto :EOF
)
set /p oldxmlname=Enter a old xml file name:
if not exist "C:\Users\roberts\Desktop\%fn%\%oldxmlname%.xml" (
echo folder not found in path.
echo "C:\Users\roberts\Desktop\%fn%"
goto :EOF
)
set /p newxmlname=Enter a new xml file name:
ren "C:\Users\roberts\Desktop\%oldxmlname%.xml" "%newxmlname%.xml"
if not errorlevel 1 (
echo file name changed successfully.
) else (
echo oops! Something is fubar
)

Related

Why batch searches files only in .bat file directory?

I'm trying to make a file search engine in batch but it searching only files in the folred where the .bat file is.
This is full code:
#echo off
title Search engine
set path=%HOMEDRIVE%
set filename=\%empty\%
set filextension=\%empty\%
cls
REM echo Under the construction
REM pause
REM call main.bat
:search
cls
echo Where do you want to search? (Leave empty for %HOMEDRIVE%)
set /p path=
:name
cls
echo Whats the name of your file? (Without extension)
set /p filename=
if %filename% == \%empty\% goto :name
:extension
cls
echo What's the extension of your file?
set /p filextension=
if %filextension% == \%empty\% goto :extension
goto :searchingMessage
:searchingMessage
cls
echo Searching %filename%.%filextension% in %path% (This may take a while)
goto :searching
:searching
for /r %path% %%a in (*) do if "%%~nxa"=="%filename%.%filextension%" set p=%%~dpnxa
if defined p (
echo File found under %p%
) else (
echo File not found
)
pause
call main.bat
Thanks. And I'm sorry if it is something simple. Im new to the batch
Use a setlocal line after #echo off. This ensures that variables that have been set within your code in one run are not preserved for the next run within the same cmd instance.
Never change the value of the variable path. It is system-defined and contains a semicolon-separated ordered list of the directories searched for an executable if that executable is not found in the current directory.
Use the syntax set "var=value" for string-assignments. This syntax ensures that any trailing spaces in a set command are not appended to the value assigned to the variable.
to assign a value of nothing (which actually deletes the variable from the environment) use the syntax set "var=". The code you have used would set the variable to \ concatenated with the value of the variable empty\. In batch, % escapes %, not \ and ^ escapes for other characters that require to be escaped USUALLY.
if %var% == something dosomething would be interpreted as if == something dosomething if var is empty, if %var% == dosomething if something is intended to be empty and if == dosomething if both are empty; all generating a syntax error since the second string following the if is not a comparison-operator like ==. To detect empty, use if defined var dosomething, if not defined var dosomething or if defined var (dosomething) else (dosomethingelse) as appropriate - noting that the string ) else (, if used, must all be on the same physical line.
Note that set /p var=whatever, or preferably set /p "var=whatever" will not change var if the response is simply Enter. It is therefore prudent to execute a set "var=" on the line before a set/p. This characteristic can be used to set a default value:
set "var=xyz"
set /p "var=new value for var [%var%] ^> "
which should prompt with new value for var [xyz] > and will retain xyz as the value of var if the response is simply Enter. Note here that the > is a special character (a redirector) so it's escaped by ^.
Note that if p is defined before the for /r ... line and no file is found, then p will not be assigned by the for /r, and will retain its original value. This is especially important in the light of point (1), where p may be retained between runs. BUT - note the possibility to use this characteristic...
set "p=File not found"
for /r ....
echo %p%
... and please use more expressive variable-names.

A script that counts and prints every ocurrence of not any file inside a common subfolder in a specific path

Although I'm really a newbie in this field, I want to accomplish a task in batch scripting: There is a determinate folder of company contracts in a determinate path, each of this folders (approx. 400) has a common folder (2016) where there might be a file indicating there has been an inspection in this year. What i want is to print every company folder that has not any file in the common 2016 folder and a count of the times this happens.
This is what i have (and does not work at all):
set c=0
for %i /d in (*) do
for %j in ($%i\2016\*) do
if (%j==NUL) then (#echo $%i c+=1 echo %c)`
If you just want to know if there is a file in the 2016 directory you can do this:
#echo off
SetLocal EnableDelayedExpansion
set count=0
for %%i /d in (*) do (
REM first unset variable
set files=
for %%j in (%%i\2016\*) do (
REM will set variable each time a file is encountered
set files=present
)
if not DEFINED files (
REM No files in directory 2016
echo %%i
set /a count+=1
echo !count!
)
)
EndLocal
exit /b 0
I don't see why you use $ before each %i. If you execute this code from the command line use one % for the loop variables i and j. But in a batch-script you'll have to use two of them (%%i, %%j).
Another thing, c+=1 won't work except if you use set /a.
I used delayed expansion because each block code ( between (...)) is parsed as one single command (as if it was all on one line with && between the commands inside the block) and you can't just assign a new value to a variable and read that new value in the same command. That's also the reason why I use !count! instead of %count% (which will give the value before the block). If you'd rather not use delayed expansion, remove the SetLocal EnableDelayedExpansion and replace echo !count! with call echo %%count%% (is another way to read a new value in the same command)
Also, be aware that each echo will end its output with a carriage retur and a newline. So each echo will result in a new line of output.

Windows script doesn't work when user types in a whitespace

I'm writing a Windows script in batch. I have a problem with whitespaces in variables. When the user types in a space, the script breaks.
Here's the part of my script:
:package
SET /P packageName="Set package name:"
IF [%packageName%] EQU [] (
ECHO Empty package name.
goto package
) ELSE (
set "packageName=%packageName: =%"
echo %packageName%
pause
)
This schould work:
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
:package
SET /P packageName="Set package name:"
IF "%packageName%"=="" (
ECHO Empty package name.
goto package
) ELSE (
set packageName=%packageName: =%
echo !packageName!
pause
)
There are two modifications to your script:
[%packageName%] EQU [] was replaced with "%packageName%"==""
I've added SETLOCAL ENABLEDELAYEDEXPANSION and changes echo %packageName% with echo !packageName!
The second point is because you are changing the value of a variable inside an IF-construction. As the interpreter doesn't know what the new value will be at "compile" time, you have to evaluate the variable at run time. That's why you need SETLOCAL ENABLEDELAYEDEXPANSION and !...! instead of %...%. This forces the expansion at run time.
I suggest to use this code:
#echo off
setlocal EnableDelayedExpansion
:package
rem Predefine variable packageName with a single double quote as value.
rem This value is kept if the user just hits RETURN or ENTER on prompt.
rem The single double quote is removed 2 command lines below if the user
rem does not enter anything or it is overwritten by user entered string.
set "packageName=""
set /P "packageName=Set package name: "
rem Remove double quotes from entered string. This is necessary to
rem avoid a syntax error on next command line with the IF condition.
set "packageName=!packageName:"=!"
if "!packageName!" == "" (
echo Empty package name.
goto package
) else (
set "packageName=%packageName: =%"
echo Package name with spaces: %packageName%
echo Package name without spaces: !packageName!
pause
)
endlocal
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.
if /?
set /?
setlocal /?
Especially the help pages output on execution of if /? should be read carefully and completely as this helps explains delayed expansion as it must be used here on examples.
See also the output of the 2 echo lines in ELSE branch in code above to understand what is the difference between referencing a variable with percent signs or with exclamation marks in blocks defined with ( ... ).
Your script is almost correct except for "variable search/replace" which its position is to be before "IF"
#echo off
:package
set /p packagename="set package name:"
set packagename=%packagename: =%
if [%packagename%] equ [] (
echo empty package name &goto package
) else (echo %packagename%)

Can some one tell me what is wrong with this bat script?

It's a simple bat script that should checkout some folders from svn . I'm not that up on bat scripting, there seems to be no consistency on how variables are referenced.
For instance the variable "branchV" does not get appended it is seen as '""', but if I echo it I see the user input.
set "DB_DIRECTORIES=AuditUser-db CarrierProcessingRules-db iDetectDB-db iRisk-db WarningsIndex-db"
set "SVNBASEURL=http://XX.XX.XX.XX:7777/svn/YYY"
set BASELOCALDIRECTORY="C:"
#echo on
#cls
#echo Check out DB directories from?
#echo
#echo 1. Trunk
#echo 2. Branch
#echo
#echo
#set OPTIONSELECTED=
#set /P OPTIONSELECTED=SELECT OPTION:%=%
if "%OPTIONSELECTED%" == "1" (
set SVNURL="%SVNBASEURL%/trunk"
set BRANCHV="BCSTrunk"
) ELSE IF %OPTIONSELECTED% == 2 (
#echo
#echo
#echo
#echo PLEASE ENTER THE BRANCH VERSION YOU WISH TO CHECKOUT
#echo
#echo
#set branchV=
#set /P branchV=ENTER VERSION:%=%
#echo
set SVNURL="%SVNBASEURL%"/branches/"%branchV%"
) ELSE (
#echo Invalid option
)
for %%i in (%DB_DIRECTORIES%) do (
set PATHTOUSE="%BASELOCALDIRECTORY%"/"%branchV%"/%%i
set NEWSVNURL="%SVNURL%"/%%i
REM Intended to remove all inverted commas , which were causing an issue in svn
set PATHTOUSE="%PATHTOUSE:=%"
set NEWSVNURL=%NEWSVNURL:=%
TortoiseProc.exe /command:checkout /path:%PATHTOUSE% /url:%NEWSVNURL% /closeonend:1
)
In batch scripts, when a line or a block of code (the code enclosed in parenthesis) is reached, all variable reads are replaced with the value they have before starting to execute that line or block. So, if you change a variable inside a block, you can not retrieve this value inside the same block. There are no reads of the variable value, they were replaced with its values.
To correctly retrieve the changed value inside the same block, it is necessary to indicate to cmd that the read operations should be delayed until the line is executed. To do this, two steps are necessary. First is enable this option
setlocal enabledelayedexpansion
When it is enabled, variables that should be read delayed need the sintax !var! instead of %var%

Batch file variable scope issue

I'm having a strange variable scope issue when trying to create a 'dos' (windows 7 command line) batch file which performs a bit of string manipulation to create new file paths. Can anyone see why the OUTPUT_FILENAME variable always ends up being null in the example below?
echo Enter the Data Input, S (Site) or U (User)
set /p DATA_TYPE=
echo.
echo Enter the Input File Name
set /p INPUT_FILENAME=
echo.
IF /I %DATA_TYPE%==u (
set OUTPUT_FILENAME=%INPUT_FILENAME:\users\=\Users\Outputs\%
set OUTPUT_FILENAME=%OUTPUT_FILENAME:xls=txt%
echo Output:
echo %OUTPUT_FILENAME%
)
IF /I %DATA_TYPE%==s (
set OUTPUT_FILENAME=%INPUT_FILENAME:\sites\=\Sites\Outputs\%
set OUTPUT_FILENAME=%OUTPUT_FILENAME:xls=txt%
echo Outputs:
echo %OUTPUT_FILENAME%
)
Thanks in advance for any assistance, this is driving me nuts!
You need to enable the delayed expansion:
setlocal EnableDelayedExpansion
echo Enter the Data Input, S (Site) or U (User)
set /p DATA_TYPE=
echo.
echo Enter the Input File Name
set /p INPUT_FILENAME=
echo.
SET OUTPUT_FILENAME=Empty
IF /I %DATA_TYPE%==u (
set OUTPUT_FILENAME=!INPUT_FILENAME:\users\=\Users\Outputs\!
set OUTPUT_FILENAME=!OUTPUT_FILENAME:xls=txt!
echo Output:
echo !OUTPUT_FILENAME!
)
IF /I %DATA_TYPE%==s (
set OUTPUT_FILENAME=!INPUT_FILENAME:\sites\=\Sites\Outputs\!
set OUTPUT_FILENAME=!OUTPUT_FILENAME:xls=txt!
echo Outputs:
echo !OUTPUT_FILENAME!
)
As the help for the SET command states:
Delayed environment variable expansion is useful for getting around the limitations of the current expansion which happens when a line of text is read, not when it is executed.
So, you need to use the delayed expansion to make sure that INPUT_FILENAME OUTPUT_FILENAME's value are expanded at execution time.
As Laf has correctly indicated, the code, as is, needs delayed expansion. In batch files, when a line or a block (all the lines enclosed in parenthesis) is reached, before being executed, it is parsed. In this parse phase, each variable read is replaced with the value the variable has before the execution starts.
If inside a block you change a variable, and want to access this changed value inside the same block, you need delayed expansion. The code in Laf answer reflect how to do it
Or, if it is possible, you can change your code to not need it
echo Enter the Data Input, S (Site) or U (User)
set /p DATA_TYPE=
echo.
echo Enter the Input File Name
set /p INPUT_FILENAME=
echo.
IF /I %DATA_TYPE%==u (
set OUTPUT_FILENAME=%INPUT_FILENAME:\users\=\Users\Outputs\%
)
IF /I %DATA_TYPE%==s (
set OUTPUT_FILENAME=%INPUT_FILENAME:\sites\=\Sites\Outputs\%
)
set OUTPUT_FILENAME=%OUTPUT_FILENAME:xls=txt%
echo Output:
echo %OUTPUT_FILENAME%
Now, there are variables changed inside blocks, but the values are then accessed out of the blocks.

Resources