I've spent a lot of time writing a script to generate new files using a "template" (coding env.) project.
While on Unix the shell script is laughably easy I spent days doing the same on Windows...
My current batch file does almost everything I need, except that the string replacement is case-insensitive... That is, it replaces "emptyproject" with "EMPTYPROJECT", being the first statement...
Code:
#echo off & setlocal ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
set argc=0
for %%x in (%*) do set /A argc+=1
if /I "%argc%" EQU "0" (
echo Usage: %0 PROJECT_NAME >&2
exit /B 1
)
set curr_dir=%~dp0
set project_name=%1
set project_name_lower=%1
set project_name_upper=%1
set project_file="vstudio\projects\%project_name%.vcxproj"
set project_filters="vstudio\projects\%project_name%.vcxproj.filters"
call :toupper project_name_upper
call :tolower project_name_lower
if not exist %project_file% (
copy /y "vstudio\projects\EmptyProject.vcxproj" %project_file% >nul
copy /y "vstudio\projects\EmptyProject.vcxproj.filters" %project_filters% >nul
)
set project_source_dir=..\projects\source\%project_name_lower%
if not exist %project_source_dir% (
mkdir %project_source_dir%
call :copy_and_replace_strings "..\projects\source\emptyproject\main.cpp" "%project_source_dir%\main.cpp" %project_name% %project_name_lower% %project_name_upper%
call :copy_and_replace_strings "..\projects\source\emptyproject\emptyproject.h" "%project_source_dir%\%project_name_lower%.h" %project_name% %project_name_lower% %project_name_upper%
call :copy_and_replace_strings "..\projects\source\emptyproject\emptyproject_main.cpp" "%project_source_dir%\%project_name_lower%_main.cpp" %project_name% %project_name_lower% %project_name_upper%
call :copy_and_replace_strings "..\projects\source\emptyproject\emptyproject_eventhandlers.cpp" "%project_source_dir%\%project_name_lower%_eventhandlers.cpp" %project_name% %project_name_lower% %project_name_upper%
)
endlocal
goto :EOF
REM functions
:toupper
for %%L IN (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) DO SET %1=!%1:%%L=%%L!
goto :EOF
:tolower
for %%L IN (a b c d e f g h i j k l m n o p q r s t u v w x y z) DO SET %1=!%1:%%L=%%L!
goto :EOF
:copy_and_replace_strings <source_file> <target_file> <name> <lower> <upper>
for /f "tokens=1,* delims=]" %%a in ('find /n /v "" ^< %1') do (
set token1=%%a
set token2=%%b
if defined token2 (
REM not case sensitive
set token2=!token2:EMPTYPROJECT=%5!
set token2=!token2:EmptyProject=%3!
set token2=!token2:emptyproject=%4!
echo !token2!>>%2
) else (
echo[>>%2
)
)
goto :EOF
I read a lot about this on this forum, but couldn't find a suitable solution. Could someone help me please?
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
FOR %%o IN (EMPTYPROJECT EmptyProject emptyproject EmPtYpRoJeCt) DO (
SET "token2=A line containing %%o in it"
CALL :magic
ECHO !token2! -^> !result!
)
GOTO :EOF
:magic
SET "result=!token2!"
ECHO !token2!|FINDSTR "EMPTYPROJECT" >NUL
IF NOT ERRORLEVEL 1 set "result=!token2:EMPTYPROJECT=capiTaLs!"
ECHO !token2!|FINDSTR "EmptyProject" >NUL
IF NOT ERRORLEVEL 1 set "result=!token2:EMPTYPROJECT=Mixed!"
ECHO !token2!|FINDSTR "emptyproject" >NUL
IF NOT ERRORLEVEL 1 set "result=!token2:EMPTYPROJECT=lower!"
GOTO :eof
Perhaps this will be of assistance.
To be rather honest, your quickest method to keep it pure batch is to trick the system and use powershell in the background.
#echo off
setlocal enabledelayedexpansion
set "input=i want this upper case"
for /f "usebackq delims=" %%a in (`powershell "\"%input%\".toUpper()"`) do set "lower=%%~a"
set "input=I WANT THIS LOWER CASE"
for /f "usebackq delims=" %%a in (`powershell "\"%input%\".toLower()"`) do set "upper=%%~a"
echo !lower!
echo !upper!
RESULT
I WANT THIS UPPER CASE
i want this lower case
Related
I want to create a script, which lower and remove special character multiple text files.
my files in folder like this:
- ⚡ Document.txt
- [Review] Test File.txt
i want remove special char of filename like this
- document.txt
- review test file.txt
i've tried like this, but only lower filename. how to remove special character?
#echo off
setlocal enableDelayedExpansion
pushd %currentfolder%
for %%f in (*) do (
set "filename=%%~f"
for %%A in (a b c d e f g h i j k l m n o p q r s t u w x y z) do (
set "filename=!filename:%%A=%%A!"
)
ren "%%f" "!filename!" >nul 2>&1
)
endlocal
Before
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcedir=u:\your files"
set "validchars=abcdefghijklmnopqrstuvwxyz1234567890. "
pushd "%sourcedir%"
FOR %%b IN (*) DO (
set "newname="
set "oldname=%%b"
call :validate
if /i "%%b" neq "!newname!" ren "%%~sb" "!newname!"
)
popd
GOTO :EOF
:validate
if not defined oldname goto :eof
set "c1=%oldname:~0,1%"
set "oldname=%oldname:~1%"
if "!validchars:%c1%=!" neq "%validchars%" set "newname=%newname%%c1%"
goto validate
Always verify against a test directory before applying to real data.
I predict it will have problems with some unicode characters and the usual suspects.
You could use pure powershell for this, or if you feel like continuing the use batch-file, just call powershell to assist:
#echo off
for %%i in (*) do for /f "delims=" %%a in ('powershell "$string='%%~ni';$String.tolower() -replace '[\W]', ''"') do echo ren "%%~i" "%%a%%~xi"
Note the echo at the end of the line, that is to test functionality by printing to screen before you do the actual renaming. Only remove echo when you're happy with the printed results.
I want to remove three digits after dot in last 3 columns with batch file (windows). Note that dots can be present in other columns.
This is a sample of my data:
4216118,'0806010709','ljubičasti ','Hita kirška ambnta',1,'Eriiti (vk, kk)','X','Uđaj za heološke prege','Celyn1800 ','Hni Sak','Hemlogja','2016-06-08 11:42:05.040','2016-06-08 11:41:42.122','2016-06-08 11:49:49.370'
4216081,'0806010387','ljubičasti ','Oća doven.amb. - VANJA',1,'Erii (vk, kk)',,'Urj za heoške prage','Adia 120 R','Reni','Hlogija','2016-06-08 08:52:13.962','2016-06-08 08:51:57.067','2016-06-08 11:08:26.504'
4216667,'1506010909','ljčasti ','tna ambuta kke za invne bolesti',1,'Erciti (vk, kk)',,'Uj za hemloške prge','Cell-Dyn 1800 R','Hi','Hemagija','2016-06-15 21:24:14.646','2016-06-15 21:24:03.523','2016-06-15 21:26:58.871'
4213710,'0905010991','ljubičasti ','Hna kira amnta',1,'Eociti (vk, kk)','X','Uđaj za hemloške prage','Cel1800 ','Hi Sak','Hemlogja','2016-05-09 17:52:32.231','2016-05-09 17:52:26.319','2016-05-09 18:31:33.643'
Example:
Before:
'2016-06-08 11:49:49.370'
After:
'2016-06-08 11:49:49'
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcedir=U:\sourcedir"
SET "destdir=U:\destdir"
SET "filename1=%sourcedir%\q47642335.txt"
SET "outfile=%destdir%\outfile.txt"
(
FOR /f "delims=" %%a IN ('more %filename1%') DO (
SET "line=%%a"
ECHO !line:~0,-57!!line:~-53,-31!!line:~-27,-5!!line:~-1!
)
)>"%outfile%"
GOTO :EOF
You would need to change the settings of sourcedir and destdir to suit your circumstances.
I used a file named q47642335.txt containing your data for my testing.
Produces the file defined as %outfile%
Sadly, cmd doesn't play nicely with unicode files, so there will be some modification to the data. Essentially, read each line and pick the line-portions to be concatenated, using - substringing values to select from the end of the line, which is of a consistent structure.
Try this, without any guaranties. Regarding your example, expect you want remove last three digits AND dot, unlike your describe to remove three digits AFTER dot.
#echo off & setlocal ENABLEDELAYEDEXPANSION > out.txt
for /f "tokens=1-15 delims=," %%a in (data.txt) do (
set "string="
call :process "%%a" "%%b" "%%c" "%%d" "%%e" "%%f" "%%g" "%%h" "%%i" "%%j" "%%k" "%%l" "%%m" "%%n" "%%o"
)
exit /B
:process
echo %~1| findstr /R /C:"[0-9]*-[0-9]*-[0-9]* [0-9]*:[0-9]*:[0-9]*\.[0-9][0-9][0-9]" >NUL
if not errorlevel 1 (
set "str=%~1"
set "str=!str:~0,-5!"
if defined string (set "string=!string!,!str!'") else (set "string='!str!'")
) else (
set "str=%~1"
if defined string (set "string=!string!,!str!") else (set "string='!str!'")
)
shift
if not "%~1"=="" (goto :process) else (echo !string!>>out.txt)
GOTO:EOF
I tried to write a batch script that find all the paths of files that have the same name as the input string. right now it can find only the first file found, and i cant think of a way to make it list multiple files locations. I am not very experienced and I need some help.
this is part of the script code:
:start
cls
echo Enter file name with extension:
set /p filename=
echo Searching...
for %%a in (C D E F G H U W) do (
for /f "tokens=*" %%b in ('dir /s /b "%%a:\%filename%"') do (
set file=%%~nxb
set datapath=%%~dpb\
::the path of the file without the filename included "C:\folder\folder\"
set fullpath=%%b
::the path of the file with the filename included "C:\folder\folder\file"
goto break
)
)
:notfound
cls
echo Enter file name with extension:
echo %filename%
echo File Not Found!
ping localhost -n 4 >nul
goto start
:break
if "%datapath:~-1%"=="\" set datapath=%datapath:~,-1%
cls
echo 3 %filename% found
echo %fullpath1%
echo %fullpath2%
echo %fullpath3%
--- || ---
I want the script to search the computer and list every encountered files with the same name and I want to be able to put those files' paths into different variables.
For example, if readme.txt is the input, then I want the list of all the paths of all the files with that specific name (readme.txt) and I want to set variable for each path so I can use it after that.
input:
readme.txt
output:
3 files found
C:\folder\folder\readme.txt
C:\folder\folder\folder\readme.txt
D:\folder\readme.txt
#echo off
set filename=readme.txt
for %%a in (C D E F G H U W) do (
for /f "tokens=*" %%b in ('dir /s /b "%%a:\%filename%"') do (
echo you can do something here with %%~nxb in %%~dpb
echo full name: %%b
)
)
I see no need to set the filenames to variables, as you can process them inside your loop. But if you really need them (for some reason) in variables:
#echo off
setlocal enabledelayedexpansion
set filename=readme.txt
set count=0
for %%a in (C D E F G H U W) do (
for /f "tokens=*" %%b in ('dir /s /b "%%a:\%filename%" 2^>nul') do (
set /a count+=1
set _file[!count!]=%%b
)
)
set _file
You can try with this code :
#echo off
Title Searching for the path with the same file name
Mode con cols=80 lines=3 & Color 9E
SET /a Count=0
set /a cnt=1
set "FileName=Readme.txt"
set "Report=%~dp0Report.txt"
set "Folder2Copy=%~dp0Readme_Folder"
set "Result2Copy=%~dp0Result2Copy.txt
If exist %Folder2Copy% RD /S /Q %Folder2Copy%
If Exist %Report% Del %Report%
If Exist %Result2Copy% Del %Result2Copy%
echo(
Echo Searching for the path with the same file name
Rem Looking for fixed drives and store them into variables
SETLOCAL enabledelayedexpansion
For /f "skip=1" %%a IN ('wmic LOGICALDISK where driveType^=3 get deviceID') DO (
for /f "delims=" %%b in ("%%a") do (
SET /a "Count+=1"
set "Drive[!Count!]=%%b"
)
)
:Display
for /L %%i in (1,1,%Count%) do (
cls
Title Please wait a while ... Searching for "%FileName%" on "!Drive[%%i]!\"
echo(
echo Please wait a while ... Searching for "%FileName%" on "!Drive[%%i]!\"
Call :FindPathFile !Drive[%%i]!\ %FileName% >> %Report%
)
Start "" %Report%
Goto :AskQuestion
::***************************************************************************************
:FindPathFile <Location> <FileName>
Where.exe /r %1 %2
Goto :eof
::***************************************************************************************
:AskQuestion
cls & Mode con cols=100 lines=5
echo(
echo Did you want to make copy of all files found as name "%FileName%"
echo saved on "%Report%" ? (Y/N) ?
set /p "Input="
If /I "%INPUT%"=="Y" (
for /f "delims=" %%i in ('Type "%Report%"') do (
Call :MakeCopy "%%~i" "%Folder2Copy%\"
)
)
Call :Explorer "%Folder2Copy%\" & exit
If /I "%INPUT%"=="N" (
Exit
)
Goto :eof
::***************************************************************************************
:MakeCopy <Source> <Target>
If Not Exist "%~2\" MD "%~2\" (
if not exist "%2\%~n1" (
echo copying "%~1" to "%~2"
copy /N /B "%~1" "%~2" >>%Result2Copy% 2>&1
) else (
call :loop "%~1" "%~2"
)
)
::***************************************************************************************
:loop
set "fname=%2\%~n1(%cnt%)%~x1"
if exist "%fname%" set /a cnt+=1 && goto :loop
copy "%~1" "%fname%"
exit /b
::***************************************************************************************
:Explorer <file>
explorer.exe /e,/select,"%~1"
Goto :EOF
::***************************************************************************************
I have to make a script that has to calculate the mask and the net, so I'm trying a script with for but it can not convert the IP to binary. I think I'm not using the variables right.
Any ideas?
#echo off
setlocal enabledelayedexpansion
set var=%1
set /p var=Introduce la ip:
for /F "tokens=1 delims=." %%a in ("%var%") do (
echo %%a
set "vara=%%a"
:binario
set bin=2
set /a resto=%vara%%%bin%
set /a a=%vara%/%bin%
set resultado=%resto%%resultado%
if %vara% GTR 0 (goto binario)
echo %resultado%
goto siguiente
)
:siguiente
for /F "tokens=2 delims=." %%b in ("%var%") do (
echo %%b
)
for /F "tokens=3 delims=." %%c in ("%var%") do (
echo %%c
)
for /F "tokens=4 delims=." %%d in ("%var%") do (
echo %%d
)
goto fin
:vacio
echo Error!
goto fin
:fin
pause
You've got a few minor problems that I see. You set var=%1 but you never check to see whether %1 was supplied before doing set /p var=Enter an IP:. You never call or goto :vacio. As I commented above, modulos within batch scripts need to be written as %% to prevent evaluation as variable chararacters. You don't need % in var names in set /a commands, and you can combine multiple set /a statements with a comma. So instead of
set /a resto=%vara%%%bin%
set /a a=%vara%/%bin%
(which is wrong anyway -- I'll get to that in a minute), I suggest this would be more understandable and maintainable:
set /a resto = vara %% bin, numero = vara / bin
The biggest problem is that you appear to be trying to modify %%a. Don't do that.
If I were you, I would move the decimal to binary conversion to a subroutine, and call it for each octet. Try this:
#echo off
setlocal enabledelayedexpansion
set IP=%1
if "%IP%"=="" set /p "IP=Introduce la ip: "
set idx=0
for %%a in (%IP:.= %) do (
if %%a lss 0 goto vacio
if %%a gtr 255 goto vacio
if !idx! gtr 3 goto vacio
set /P "=%%a = "<NUL
call :dec2bin bin[!idx!] %%a
set /a idx += 1
)
echo %bin[0]%.%bin[1]%.%bin[2]%.%bin[3]%
goto fin
:dec2bin <var_para_definir> <numero>
setlocal enabledelayedexpansion
set numero=%~2
set bin=
for /L %%I in (1,1,8) do (
set /a bit = numero %% 2, numero /= 2
set bin=!bit!!bin!
)
echo %bin%
endlocal & set "%~1=%bin%"
goto :EOF
:vacio
echo Error!
goto fin
:fin
pause
For more information about using call as a function that returns a value, see this page.
In windows batch files, I know %1 is replaced with the first argument, %2 is replaced with the 2nd argument and %* is replaced with all arguments.
Is there a way to get all the arguments after the 1st one? (e.g. arguments 2-N) What about all the arguments after the 2nd one?
The SHIFT command doesn't seem to affect %*.
#ECHO OFF
SETLOCAL
CALL :allafter 3 %*
ECHO args=%args%
GOTO :eof
:allafter
FOR /l %%a IN (1,1,%1) DO SHIFT
(SET args=)
:argloop
shift
IF NOT .%1==. SET args=%args% %1&GOTO argloop
IF DEFINED args SET args=%args:~1%
GOTO :eof
to get everything after the 3rd argument to ARGS
Edit - to take care of space-separated elements which may include commas
#ECHO OFF
SETLOCAL
CALL :allafter 3 %*
ECHO args=%args%
CALL :allafter2 3 %*
ECHO args=%args%
GOTO :eof
:allafter
FOR /l %%a IN (1,1,%1) DO SHIFT
(SET args=)
:argloop
shift
IF NOT .%1==. SET args=%args% %~1&GOTO argloop
IF DEFINED args SET args=%args:~1%
GOTO :EOF
:allafter2
SET /a count=%1
SET args=%*
:arg2loop
SET oldargs=%args%
call SET args=%%args:*%1 =%%
IF "%args%"=="%oldargs%" (call SET args=%%args:*%1,=%%) ELSE (SET /a count-=1)
shift
IF %count% gtr -1 GOTO arg2loop
GOTO :EOF
Hmm- spoke too soon. This modified routine should play nicer. The previous version treated what was to be defined as one argument one,two,three as three separate arguments when the remove-leading-n was invoked.
Well, there is a way-ish...
By using the /n switch on the shift command, you can sort of do something like it. However, it will delete all of the argument and put them into a certain variable (so you can't call %3 anymore without a for loop).
#setlocal enableextensions
#echo off
:loop
if "%~2" equ "" goto end
set variable=%variable% %~2
shift /2
goto loop
:end
echo %1
echo %variable%
endlocal
To separate the parameters again just do a simple for loop (I'm sure you can find documentation on it somewhere).
Solution without shift & goto:
#echo off &setlocal enabledelayedexpansion
set /a count=0
for %%i in (%*) do set /a count+=1
set "args="
for /l %%i in (2,1,%count%) do if defined args (call set "args=!args! %%%%i") else call set "args=%%%%i"
echo.%args%
endlocal
> type t.bat
#echo off
echo %*
for /f "tokens=1,*delims= " %%i in ("%*") do echo %%j
> t a b c d e f,g h i
a b c d e f,g h i
b c d e f,g h i
> t a,a b c d e f,g h i
a,a b c d e f,g h i
b c d e f,g h i
>