I need to add in a conditional statement to check for a folder so that it can exexute the below script. Lets say the script is placed in folder c:/temp/A but I want the script to excute and change the file extensions of files in a another directory d:/xxx/B. If directory B doesnt exists, throw an error and exit. I tried using if else statement but its says no else statement is allowed. Please help me out and let me know how it can be done.
#echo off
setlocal ENABLEDELAYEDEXPANSION
for %%F in (*.*_error* *.*error_*) do ( set "ext=%%~xF"
SET "ext=!ext:_error=!"
ren "%%F" "%%~nF!ext:error_=!"
)
You can do a condition like this.
IF EXIST "D:\xxx\b\" (goto thescript) else goto theerror
:thescript
#then whatever you want to run here.
goto :EOF
:theerror
ECHO File does not exist
goto :EOF
#echo off
setlocal ENABLEDELAYEDEXPANSION
PUSHD d:\xxx\B 2>nul
if errorlevel 1 (
echo required destination not found
goto :wherever
)
for %%F in (*.*_error* *.*error_*) do ( set "ext=%%~xF"
SET "ext=!ext:_error=!"
ren "%%F" "%%~nF!ext:error_=!"
)
POPD
Best idea to use the correct character for directoryname-separators. / is used for switches.
Related
I have problem with batch. I want to create new dir and save file to it everytime batch is opened
This is sample of my code
SET i=0
FOR /L %%i IN (0,1,100) DO (
IF NOT EXIST res\%%i (
mkdir res\%%i
GOTO run
)
)
:run
start X.exe /stext res\%i%\X.txt
Creating folders works properly. I have problem with
start X.exe /stext res\%i%\X.txt
Thanks
%i% and %%i are totally different variables. %i% is a regular batch variable, while %%i only exists within the for loop. Once you call goto run, it no longer exists.
You can store %%i in a variable and then call it using delayed expansion, because you're setting it inside of a code block (a set of parentheses).
#echo off
setlocal enabledelayedexpansion
SET i=0
FOR /L %%i IN (0,1,100) DO (
IF NOT EXIST res\%%i (
set i=%%i
mkdir res\!i!
GOTO run
)
)
:run
start X.exe /stext res\!i!\X.txt
#echo off
setlocal enabledelayedexpansion
for %%j in ("*") do (
set filename=%%~nj
set filename="!filename:(1)=!"
if not "!filename!" == "%%~xj" ren "%%j" "!filename!%%~xj"
)
The problem with the script is I will get a syntax error if a file has ! in its filename. What can I replace !filename! with to avoid this error?
Do the task keeping delayed expansion disabled. Furthermore, following commented .bat script respects the facts that
rename command would fail if target file already exists (otherwise, an error A duplicate file name exists, or the file cannot be found is raised), and
currently running .bat/.cmd script can't be renamed/deleted.
The script correctly handles all cmd/.bat special characters if valid in file names like ^ caret, % percent sign etc.:
#ECHO OFF
SETLOCAL EnableExtensions DisableDelayedExpansion
set "filemask=*" original file mask
rem prepare background for debugging and demonstration
pushd "D:\bat\Unusual Names"
set "filemask=0*!*.txt" narrowed file mask
for %%j in ("%filemask%") do (
if /I "%%~fj"=="%~f0" (
rem do not rename currently running script "%~f0"
rem applicable if %filemask% does not exclude %~x0 extension i.e. .bat/.cmd
rem e.g. if "%filemask%"=="*"
) else (
set "file=%%~j" name and extension
set "filename=%%~nj" name only
set "fileext=%%~xj" extension only
call :renFile
)
)
popd
ENDLOCAL
goto :eof
:renFile
set "filename=%filename:(1)=%"
if not "%filename%%fileext%"=="%file%" (
if exist "%filename%%fileext%" (
rem renaming is not possible as target file already exists
echo ??? "%file%"
) else (
rem rename command is ECHOed merely for debugging and demonstration
rem make it operational no sooner than debugged
ECHO ren "%file%" "%filename%%fileext%"
)
) else (
rem output for debugging and demonstration
echo NER "%filename%%fileext%"
)
goto :eof
Sample output:
==> dir /B "D:\bat\Unusual Names\0*!*.txt"
01exclam!ation(1).txt
02exc!lam!ation.txt
03exclam!ation!OS!(1).txt
04exc!lam!ation!OS!%OS%(1).txt
04exc!lam!ation!OS!%OS%.txt
==> D:\bat\SO\41714127.bat
ren "01exclam!ation(1).txt" "01exclam!ation.txt"
NER "02exc!lam!ation.txt"
ren "03exclam!ation!OS!(1).txt" "03exclam!ation!OS!.txt"
??? "04exc!lam!ation!OS!%OS%(1).txt"
NER "04exc!lam!ation!OS!%OS%.txt"
==>
Basically you need to toggle delayed expansion, so that the for variables are expanded when it is disabled -- like this:
#echo off
setlocal DisableDelayedExpansion
for %%j in ("*") do (
set "file=%%~j"
set "filename=%%~nj"
set "fileext=%%~xj"
setlocal EnableDelayedExpansion
set "filename=!filename:(1)=!"
if not "!filename!"=="!fileext!" (
ren "!file!" "!filename!!fileext!"
)
endlocal
)
Besides that, I corrected the quotation. Note that I did not further check the logic of your script.
I was looking for a long time now for an answer to this, learned nice tricks from http://www.dostips.com/DtTutoPersistency.php and http://ss64.com/nt/for_cmd.html sites, but still - don't have a solution to the problem I've encountered in:
I have a BATCH file where I test the existence of specific folder (SendTo folder). In case I couldn't find it by the script - I want the user to enter the path to that folder - and keep the result in the BATCH file.
My narrowed BATCH file ("Some file.bat") looks something like:
#echo off
REM SomeNonsense
:: Win7/Vista
IF EXIST %APPDATA%\Microsoft\Windows\SendTo\NUL (
REM Do something
GOTO :EOF
)
:: WinXP
IF EXIST %USERPROFILE%\SendTo\NUL (
REM Do something
GOTO :EOF
)
:: Else
SET SendPath=
SET /P SendP="Please enter the path to the SendTo Folder:> "
IF EXIST %TMP%\SendPath.txt DEL %TMP%\SendPath.txt
FOR /F "usebackq TOKENS=* DELIMS=" %%A in ("%~0") DO (
ECHO %%A>>%TMP%\SendPath.txt
REM Later I want to change the value of SendPath with SendP,
REM And swap the file back to the original name
)
My problem right now is that the lines of the file actually being interpreted, when I want only to copy the text itself to a temp file (without using COPY, because I want to copy line by line in order to change SendPath value).
Another thing is that empty lines aren't copied.
Any solution?
This do what you want:
#echo off
rem Your previous Win7/Vista, WinXP testings here...
:: Else
call :defineSendPath
if defined SendPath goto continue
SET /P "SendPath=Please enter the path to the SendTo Folder:> "
rem Store the SendPath given into this Batch file:
echo set "SendPath=%SendPath%" >> "%~F0"
:continue
rem Place the rest of the Batch file here...
goto :EOF
rem Be sure that the following line is the last one in this file
:defineSendPath
As a proof of concept
#echo off
setlocal enableextensions disabledelayedexpansion
call :persist.read
if not defined savedValue (
set /p "savedValue=Value to save:" && ( call :persist.write savedValue ) || (
echo Value not set, process will end
exit /b 1
)
)
echo Saved value = [%savedValue%]
goto :eof
:persist.read
for /f "tokens=1,* delims=:" %%a in ('
findstr /l /b /c:":::persist:::" "%~f0"
') do set "%%~b"
goto :eof
:persist.write varName
if "%~1"=="" goto :eof
for %%a in ("%temp%\%~nx0.%random%%random%%random%.tmp") do (
findstr /l /v /b /c:":::persist::: %~1=" "%~f0" > "%%~fa"
>"%~f0" (
type "%%~fa"
echo(
setlocal enabledelayedexpansion
echo(:::persist::: %~1=!%~1!
endlocal
)
del /q "%%~fa"
)
goto :eof
The problem with a batch file that edits itself while running is that it keeps pointers to the character position in the file where the commands are being executed. You can only make changes in lines after the current executing one and this can also generate other problems. So, the safest (not the more elegant nor the fastest) generic approach could be to write the data as comments at the end of the file.
Looking for ideas to help me with this.
I have a lot of music and most of it is in order of [artist folder] [album folder] [cd folder] [files] and I want to quickly be able to bring all music files under [artist] level.
I'm not expecting miracles so I'm thinking if I can set it up as a right click command much like WinRar does with Extract Here, that should bring everything from that folder up a level?
So I need to be able to
call my batch , and pass it the target folder.
Have the batch select all files/folders within and move to the
same level as target folder.
Trying to keep it simple even if I need to r/click several times for one artist!
Thanks in advance for any help, pointers or further reading!
Here is a script to move all files under a root directory to the root.
"Moveit.bat C:\my\music"
will find everything under that directory and move them into C:\my\music.
Line 27 is commented out ... so the script will only tell you what it would do.
Uncomment line 27 for it to actually work.
#echo off
#rem USAGE: MoveIt root
setlocal
pushd "%~1"
set root=%CD%
if "%1"=="" goto :Usage
for /f "delims=;" %%a in ('dir /a-d /b /s ') do call :MoveIt "%%a"
goto :EOF
:MoveIt
rem Exclude files directly under "from"
set target=%~d1%~p1
if "%target:~2%"==":\" (
if "%target%"=="%root%" (
goto :EOF
)
) else if "%target:~0,-1%"=="%root%" (
goto :EOF
)
echo move "%~1" "%root%"
rem move "%~1" "%root%" > nul || echo Failed to move "%~1" to "%root%" & goto :EOF
goto :EOF
:Usage
echo Usage: moveit.bat RootDirectory
goto :EOF
I want to have my batch file to recognise the extension of the file the user types in in the following situation:
The user has to type in a folder OR a .zip/.rar file.
if its a folder, it should use GOTO :folder
if its a .zip/.rar, it should use GOTO :ziprar
(if it is possible without 3rd party software, than dont going to say about it please)
You can extract substrings from environment variables, which you can use to get the file extension:
set FILENAME=C:\mypath\myfile.rar
if "%FILENAME:~-4%"==".rar" (
echo It is a RAR file!
) else (
echo Not a RAR file
)
If the user can specify the path as a parameter to the batch file, that is the best option since "%~1" is less problematic than "%filename%" like I said in a comment to Helen's answer. It would look something like:
setlocal ENABLEEXTENSIONS
FOR %%A IN ("%~1") DO (
IF /I "%%~xA"==".rar" goto ziprar
IF /I "%%~xA"==".zip" goto ziprar
)
goto folder
If you can't use a parameter, the best I could come up with is:
setlocal ENABLEEXTENSIONS
REM set file="f~p 'o%OS%!OS!^o%%o.rar"
set /p file=Enter a folder path or a zip/rar file name:
FOR /F "tokens=*" %%A IN ("%file%") DO (
IF /I "%%~xA"==".rar" goto ziprar
IF /I "%%~xA"==".zip" goto ziprar
)
goto folder
There is a possibility that there is a valid filename that causes syntax errors, but I did not find one during my limited testing.
You might also want to consider a basic folder check rather than checking file extensions:
IF EXIST "%~1\*" (goto folder) ELSE goto ziprar