Añadir y/o sustituir texto en un archivo mediante archivo .bat

Tengo que hacer una búsqueda de texto dentro de unos archivos, en este caso archivos "services", "hosts" y un archivo .ini en una carpeta de c:\...

Para automatizar la tarea -se trata de una instalación en 50 PCs- he creado un archivo .bat -sé que no es la mejor opción para estas cosas pero, francamente, en programación no soy malo, soy nefasto... jeje, así que no puedo usar .vbs u otra herramienta pues no las conozco y ya que estamos voy a reconocer que ya tampoco tengo claro que conozca los archivos por lotes... [looco].

En fin que he creado el siguiente código, que busca una cadena de texto, si no la encuentra crea un nuevo :

@echo on &setlocal

set "ruta=%windir%\system32\drivers\etc"
set "search=servihuseapa 1528/tcp #informix"
set "replace=servihuseapa 1528/tcp #informix Modificado"
set "textfile=%ruta%\services"
set "newfile=%ruta%\services_new"


Findstr servihuseapa "%textfile%" >> "%ruta%\tempfile"

if %errorlevel% == 0 (

(for /f "delims=" %%i in ('findstr /i "^" "%textfile%"') do (
set "line=%%i"
setlocal enabledelayedexpansion
set "line=!line:%search%=%replace%!"
echo(!line!
endlocal
))>"%newfile%"
type "%newfile%"

) else (

echo %replace% >> "%ruta%\services"

)

del "%ruta%\tempfile"


El problema que me da es que, en lugar de generar una salida que incluya el texto del fichero origen y, solamente la nueva línea, es decir, algo así como:

sapgw99 3399/tcp
servihuseapa 1528/tcp #informix Modificado


Cuando el original del texto era:

sapgw99 3399/tcp
servihuseapa 1528/tcp #informix Modificado


Me retorna un nuevo fichero que contiene, el contenido original del fichero services, el nuevo apunte y, además, mi propio código por cada línea de información que tuviese... Es decir, lo siguiente:

C:\Users\s027558\Downloads\PatWIN HUSE\Test>(
set "line=sapgw99 3399/tcp"
setlocal enabledelayedexpansion
set "line=!line:servihuseapa 1528/tcp #informix=servihuseapa 1528/tcp #informix Modificado por Mateu!"
echo(!line!
endlocal
)
sapgw99 3399/tcp

C:\Users\s027558\Downloads\PatWIN HUSE\Test>(
set "line=servihuseapa 1528/tcp #informix Modificado por Mateu "
setlocal enabledelayedexpansion
set "line=!line:servihuseapa 1528/tcp #informix=servihuseapa 1528/tcp #informix Modificado por Mateu!"
echo(!line!
endlocal
)
servihuseapa 1528/tcp #informix Modificado por Mateu Modificado


Lo jodido es que el código de búsqueda, sustitución y creación del nuevo archivo por sí solo, sin la condición IF, funciona correctamente...


@echo off & setlocal
set "search=servihuseapa 1528/tcp #informix"
set "replace=servihuseapa 1528/tcp #informix Modificado por Mateu"
set "textfile=C:\Users\s027558\Downloads\PatWIN HUSE\Test\services_test"
set "newfile=C:\Users\s027558\Downloads\PatWIN HUSE\Test\services_new"


(for /f "delims=" %%i in ('findstr /i "^" "%textfile%"') do (
set "line=%%i"
setlocal enabledelayedexpansion
set "line=!line:%search%=%replace%!"
echo(!line!
endlocal
))>"%newfile%"
type "%newfile%"


Ya no veo ni qué hago... Agradecería una manita por vuestra parte...

Gracias.
Los ficheros por lotes mas que con if - else se hacían con if y gotos, prueba así:


@echo on &setlocal

set "ruta=%windir%\system32\drivers\etc"
set "search=servihuseapa 1528/tcp #informix"
set "replace=servihuseapa 1528/tcp #informix Modificado"
set "textfile=%ruta%\services"
set "newfile=%ruta%\services_new"


Findstr servihuseapa "%textfile%" >> "%ruta%\tempfile"

IF %errorlevel% == 1 GOTO ERROR
IF %errorlevel% == 0 GOTO OK

:OK
(for /f "delims=" %%i in ('findstr /i "^" "%textfile%"') do (
set "line=%%i"
setlocal enabledelayedexpansion
set "line=!line:%search%=%replace%!"
echo(!line!
endlocal
))>"%newfile%"
type "%newfile%"

goto fin

:ERROR
echo %replace% >> "%ruta%\services"

:fin

del "%ruta%\tempfile"

Por probar...
Mueve la linea 'setlocal enabledelayedexpansion' al principio del fcihero bat (despues de echo off) y en linea independiente (sin el '&' despues del echo off)
Quizás haciendo como comenta @lecquio puede funcionar. El CMD se suele liar bastante con los IF.

No obstante, hay un par de cosas que quizás también podría hacer que falle en algún escenario: Estas usando >> invariantemente para escribir en los archivos. Cuando pones >>, el texto lo añades al fichero existente (y si no existe, se crea); sin embargo si pones >, se sustituye el contenido entero del fichero por lo que estás escribiendo. No sé si es lo que quieres hacer al escribir en "%ruta%\services". Si es correcto, ignora lo que te comento.

Por otra parte, no entiendo por qué usas Findstr servihuseapa "%textfile%" >> "%ruta%\tempfile" para crear un archivo temporal, si luego no lo usas y lo borras al final. ¿No sería mejor usar > nul para que no haya salida y así te ahorras tener que escribir en ese archivo?
lecquio escribió:Los ficheros por lotes mas que con if - else se hacían con if y gotos, prueba así:


@echo on &setlocal

set "ruta=%windir%\system32\drivers\etc"
set "search=servihuseapa 1528/tcp #informix"
set "replace=servihuseapa 1528/tcp #informix Modificado"
set "textfile=%ruta%\services"
set "newfile=%ruta%\services_new"


Findstr servihuseapa "%textfile%" >> "%ruta%\tempfile"

IF %errorlevel% == 1 GOTO ERROR
IF %errorlevel% == 0 GOTO OK

:OK
(for /f "delims=" %%i in ('findstr /i "^" "%textfile%"') do (
set "line=%%i"
setlocal enabledelayedexpansion
set "line=!line:%search%=%replace%!"
echo(!line!
endlocal
))>"%newfile%"
type "%newfile%"

goto fin

:ERROR
echo %replace% >> "%ruta%\services"
goto fin

del "%ruta%\tempfile"



Muchas gracias @lecquio! el lunes lo modificaré con tus propuestas y comento!

@jb_______ gracias por tu comentario, de todos modos iré con la propuesta de @lecquio en primer lugar ya que tiene muy buena pinta, aunque, quizás tenga que combinar ambas...

@juananBow, como dices, en tu primer párrafo, es así, si no existe el texto en el fichero "services" original quiero añadir la cadena de texto en el fichero existente (lo que ya sería la hostia es ordenarlo por puertos... pero creo que con un bat será imposible o muy complicado...). Es decir, necesito añadir ese servicio, puerto y protocolo a la lista de servicios detallados en el archivo "services" de Windows en el caso de que no exista, en cambio si existe reemplazarlo por los nuevos básicamente esa es la función del bat. Cuando eso funcione, meteré código para hacer lo mismo con el archivo "hosts" y los ".ini" de la aplicación...

Se trata de una aplicación que utiliza una BBDD Informix y se han migrado la versión de la app y, asimismo, se ha creado una nueva BBDD y hay que hacer las correcciones de conexión en esos tres ficheros, además, de modificar algunas claves de registro... Para evitar que los técnicos de micro tengan que hacer todo manualmente, mi intención es hacerles ese .bat para facilitarles la tarea de migración en los 50 PCs que comenté en el post original.

En cuanto a tu segunda observación, tienes razón con eso valdría, eso quedó así después de hacer varias pruebas intentando meter el valor que me daba findstr en una variable para utilizarla en el IF pero... parece que en los bat eso no funciona así... por lo que, decidí utilizar ERRORLEVEL para ello pero dejé la función de crear el archivo... en fin, que como dices, dejé basurilla y aprovechando tu comentario la limpiaré... gracias a ti también.

El lunes os digo si con vuestras propuestas funciona como debe!

Gracias a todos y saludos.
@Madoc Lo he editado que tenía un error.
Ya nos contarás a ver si hay suerte.
lecquio escribió:@Madoc Lo he editado que tenía un error.
Ya nos contarás a ver si hay suerte.


Gracias por el aviso! El lunes comento aunque, en cualquier caso, vaya mi agradecimiento a todos por adelantado!

EDITO:

He probado las soluciones propuestas pero no consiguen el efecto deseado... funciona para la adición del texto cuando este no está en el fichero original pero, cuando se trata de crear el nuevo fichero con las línea sustituida, lo crea incluyendo, además, del texto original y el nuevo texto, añadiendo el propio código... vamos, resumiendo, que el problema sigue siendo el mismo que el descrito en mi primer post.
Hola a todos,

Por fin puedo postear de nuevo... tenía que esperar 5 días o seguir editando el último post...

En primer lugar, gracias a todos los que propusisteis alguna mejora/idea!

La solución que apliqué al final es la siguiente (espero que os pueda servir de ayuda):


@echo on &setlocal

set "ruta=%windir%\system32\drivers\etc\"
set "replace=servihuseapa    1528/tcp             #informix nuevo PATWIN"
set "textfile=%ruta%\services"
set "newfile=%ruta%\services_new"


Findstr servihuseapa "%textfile%">NUL

IF %errorlevel% == 1 GOTO ERROR
IF %errorlevel% == 0 GOTO EDITAR


:EDITAR
setLocal EnableDelayedExpansion
for /f "tokens=* delims= " %%a in (services) do (
set str=%%a
set str=!str:servihuseapa=servihuseapa    1528/tcp             #informix # AntiguoServicio servihuseapa:!
echo !str!>>"%newfile%
)
endlocal
POPD
goto RENAME


:ERROR
echo %replace% >> "%ruta%\services"
goto FIN


:RENAME
IF EXIST "%newfile%" move /Y "%newfile%" "%textfile%"
goto FIN


:FIN

7 respuestas