1
\$\begingroup\$

I want to edit Windows hosts file in the best way for the end user, using a batch-only solution. I ended up with this script, which works fine, but since I don't have enough knowledge, the syntax is very poor. So please, may you take a look and tell me how to improve it, especially the =999 part (for some reason I can't use there =replaced, and can't use =0 as it breaks future iterations):

REM In short:
REM   FOR for every line of the hosts file
REM     FOR to check current line if it contains our hosts and replace if so
REM   FOR for our hosts if they not been replaced and thus shall be inserted at the end of the hosts file

@echo off
setlocal enabledelayedexpansion

set hostspath=%SystemRoot%\System32\drivers\etc\hosts

set hosts[0]=first.host.com
set hosts[1]=second.host.com
set ip=127.1.2.3

set hostslenght=0
:hostsLenght
if defined hosts[%hostsLenght%] ( 
    set /a "hostslenght+=1"
    GOTO :hostslenght
)

>"%hostspath%.new" (
    set /a hostslenght-=1
    for /f "delims=: tokens=1*" %%a in ('%SystemRoot%\System32\findstr.exe /n /r /c:".*" "%hostspath%"') do (
        set skipline= 
        for /L %%h in (0,1,!hostslenght!) do (
            echo %%b|find "!hosts[%%h]!" >nul
            if not errorlevel 1 (
                echo %ip%       !hosts[%%h]!
                set /a hosts[%%h]=999
                set skipline=true
            )
        )
        if not "!skipline!"=="true" (echo.%%b)
    )

    for /L %%h in (0,1,!hostslenght!) do (
        if not !hosts[%%h]!==999 (
            echo %ip%       !hosts[%%h]!
        )
    )
)

REM move /y "%hostspath%" "%hostspath%.bak" >nul || echo Can't backup %hostspath%. Try run the script as Administrator.
REM move /y "%hostspath%.new" "%hostspath%" >nul || echo Can't update %hostspath%. Try run the script as Administrator.

endlocal
echo The hosts file is updated.
pause

It would be great to get rid of set /a hostslenght-=1 (initially I wanted to decrement this in for loops, but it's wont decremented that way), and the last for as well.

Upd: Version 2. Horrible =999 is defeated, but there is still problems with hostslenght (is there a way to not enumerate the hosts count?), and it will be nice to preserve original file's last line (echo is always leave empty line at the end, but I don't see a easy way to detect last for iteration)

Before:

...
set /a hosts[%%h]=999
...
if not !hosts[%%h]!==999 (

After:

...
set hosts[%%h]=
...
if defined hosts[%%h] (
New contributor
NSp is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
\$\endgroup\$
4
  • \$\begingroup\$ Oof. Why batch? If you're specifically targeting Windows, PowerShell is more ergonomic. \$\endgroup\$
    – Reinderien
    Nov 24 at 0:34
  • \$\begingroup\$ @Reinderien Batch is simpler for end user, just download and run. And such solution is a classic in my specific case. \$\endgroup\$
    – NSp
    Nov 24 at 3:29
  • 1
    \$\begingroup\$ It looks like your goal is to map multiple hostnames to 127.0.0.1 as a kind of black hole, and you want to do this on multiple machines that you manage? How are you deploying and getting this script to run on your hosts? It seems like it would be far more practical to run your own DNS proxy server (such as dnsmasq or similar). \$\endgroup\$ Nov 24 at 4:01
  • \$\begingroup\$ @200_success For the end user, it's just a way to use some application with my server without editing the application files. I already have a good script for those who expect nothing but a working application, but I also want to have the perfect script for those who will check its source before running it. \$\endgroup\$
    – NSp
    2 days ago

Your Answer

NSp is a new contributor. Be nice, and check out our Code of Conduct.

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.