Link to home
Start Free TrialLog in
Avatar of Luis Diaz
Luis DiazFlag for Colombia

asked on

Windows Batch & Powershell & VBS Script: add text in between

Hello experts,

I have the following SVG file.
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"><path d="M230 798c12 0 21-10 21-21 0-12-9-22-21-22h-32c-5 0-9-2-12-6s-4-8-4-15V232c-1-10 6-18 14-19h28c6 0 11-3 16-8 4-4 6-10 5-16-1-10 6-18 14-19h57c10 1 17 10 16 19-1 6 1 12 5 17 4 4 10 7 16 7l25-1c10 2 17 10 16 22v11c0 11 10 21 21 21 12 0 22-10 22-21v-9c3-33-22-62-57-66h-8c-7-23-27-40-54-43h-61c-25 3-45 20-52 43h-12c-33 4-57 33-53 64v498c-2 16 3 31 13 44 10 12 24 20 43 22h34zm379 100c22 0 43-9 59-26 15-21 23-46 21-70V440h112c22 1 43-5 63-21 29-28 29-75-2-105-18-14-40-20-61-19H413c-22-1-43 5-62 19-15 14-24 34-23 53-1 20 8 40 24 55 18 13 39 19 60 18h115v361c-2 25 6 50 23 72 15 16 36 25 58 25h1zM410 397c-12 1-23-2-31-8-5-5-8-13-8-22 0-8 3-16 7-19 9-7 21-11 34-10h391c12-1 24 2 31 8 12 12 12 31 2 41-9 7-21 11-33 10H647v407c1 15-4 30-12 40-7 7-16 12-26 12-11-1-21-5-27-11-9-12-13-26-12-43V397H410zm-52 401l25-1c32-3 57-33 54-63V489c0-12-10-22-22-22-11 0-21 10-21 22v247c1 9-6 18-14 19h-22c-12 0-21 9-21 21s9 22 21 22z"/></svg>

Open in new window

I have multiple SVG files with the same structure.
The idea is to read all SVG files located in specific folder and generate new version in another folder with the following structure:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
<path style="fill: #888" d="M230 798c12 0 21-10 21-21 0-12-9-22-21-22h-32c-5 0-9-2-12-6s-4-8-4-15V232c-1-10 6-18 14-19h28c6 0 11-3 16-8 4-4 6-10 5-16-1-10 6-18 14-19h57c10 1 17 10 16 19-1 6 1 12 5 17 4 4 10 7 16 7l25-1c10 2 17 10 16 22v11c0 11 10 21 21 21 12 0 22-10 22-21v-9c3-33-22-62-57-66h-8c-7-23-27-40-54-43h-61c-25 3-45 20-52 43h-12c-33 4-57 33-53 64v498c-2 16 3 31 13 44 10 12 24 20 43 22h34zm379 100c22 0 43-9 59-26 15-21 23-46 21-70V440h112c22 1 43-5 63-21 29-28 29-75-2-105-18-14-40-20-61-19H413c-22-1-43 5-62 19-15 14-24 34-23 53-1 20 8 40 24 55 18 13 39 19 60 18h115v361c-2 25 6 50 23 72 15 16 36 25 58 25h1zM410 397c-12 1-23-2-31-8-5-5-8-13-8-22 0-8 3-16 7-19 9-7 21-11 34-10h391c12-1 24 2 31 8 12 12 12 31 2 41-9 7-21 11-33 10H647v407c1 15-4 30-12 40-7 7-16 12-26 12-11-1-21-5-27-11-9-12-13-26-12-43V397H410zm-52 401l25-1c32-3 57-33 54-63V489c0-12-10-22-22-22-11 0-21 10-21 22v247c1 9-6 18-14 19h-22c-12 0-21 9-21 21s9 22 21 22z"/>
</svg>

Open in new window

1.The script should add
style="fill: #888" between : path and d=
2.In the script I should be able to put the StringToAdd, FirstStringInBetween and the LastStringInBetween as parameter. If you have questions, please contact me.
Example:
StringToAdd='style="fill: #888"'
FirstStringInBetween='path'
LastStringInBetween='d='
Thank you for your help.
Avatar of Bill Prew
Bill Prew

So if there is currently anything between those two match strings, it should be removed and replaced with the string to insert?
Avatar of Luis Diaz

ASKER

Indeed, this can be also another approach.

OldString='path d='
NewString='path style="fill: #888" d='

And all the files located in the SourceFolder which contains the OldString will be generated in DestFolder with NewString.

Regards,
Luis.
Probably this can help us:

Powershell:

#Replace specific values reported at $Replace variable for files located in $Basefolder

#Specify variables to work for
$CurrentFolder = Split-Path $script:MyInvocation.MyCommand.Path 
$BaseFolder = $CurrentFolder + '\Root'
$Replace = @{
"Tom" = "tata"
"Susan" = "Sue"
}
Get-ChildItem -Path $BaseFolder | % {
"Processing $($_.FullName) ..." | Write-Host
$Content = Get-Content -Path $_.FullName | Out-String
$Replace.GetEnumerator() | % {$Content = $Content.Replace($_.Name, $_.Value)}
$Content | Set-Content -Path $_.FullName
}

Open in new window



Windows batch: based on Control.txt
@echo off
setlocal EnableDelayedExpansion
rem cd %cd%

rem Specify files and folders to work with
set CurrentDir=%~dp0
set BaseDir=%CurrentDir%Root
set ControlFile=%CurrentDir%Control.txt
set LogFile=%CurrentDir%Log.txt

rem Delete any old log file
if exist "%LogFile%" del "%LogFile%"

rem Read replacement pairs from control file, place in variables "OldText_nnn" and "NewText_nnn"
set MaxControl=0
for /f "tokens=1-2 delims=;" %%A in ('type "%ControlFile%"') do (
    set /a MaxControl += 1
    set "OldText_!MaxControl!=%%~A"
    set "NewText_!MaxControl!=%%~B"
)

rem Process all matching files in all subfolders
for /f "tokens=*" %%A in ('dir /b /s /a-d "%BaseDir%\*.*"' ) do (

    rem Skip any files with no extension
    if "%%~xA" NEQ "" (

        rem Keep track of how many lines we change
        set ChangedLines=0

        rem Delete any old file with the new name
        if exist "%%~dpnA_new%%~xA" del "%%~dpnA_new%%~xA"

        rem Read each line of this file
        for /f "tokens=*" %%B in ('type "%%~A"') do (

            rem Save line content in variables
            set OldLine=%%B
            set NewLine=%%B

            rem Perform each replacement from control file
            for /l %%i in (1,1,%MaxControl%) do (
                call set "NewLine=%%NewLine:!OldText_%%i!=!NewText_%%i!%%"
            )

            rem Check if any changes on this line, add to count if so
            if "!OldLine!" NEQ "!NewLine!" set /a ChangedLines += 1

            rem Echo new line to new file
            echo.!NewLine!>>"%%~dpnA_new%%~xA"
        )

        rem Report if changes were made to this file in log file
        if !ChangedLines! GTR 0 (
            echo.Changed "!ChangedLines!" line^(s^) in file "%%~A">>"%LogFile%"
            del "%%~A"
            ren "%%~dpnA_new%%~xA" "%%~A"
        ) else (
            del "%%~dpnA_new%%~xA"
        )

    )
)
Pause

Open in new window


If you have a best proposal please let me know.
This is XML, so it should be treated as such.
This will add the attribute 'style' somewhere inside the <path> node; XML doesn't care in which textual order attributes are listed.
$source = 'C:\Temp\Source'
$target = 'C:\Temp\Target'
$attributes = @{
	'style' = "fill: #888"
}
Get-ChildItem -Path $source -Filter *.svg | ForEach-Object {
	Write-Host "Processing '$($_.Name)' ..." -NoNewline
	$xml = [xml](Get-Content -Path $_.FullName)
	$nsMgr = [System.Xml.XmlNamespaceManager]$xml.NameTable
	$nsMgr.AddNamespace('s', $xml.svg.xmlns)
	$nodePath = $xml.SelectSingleNode('s:svg/s:path', $nsMgr)
	ForEach ($att in $attributes.Keys) {
		$nodePath.SetAttribute($att, $attributes[$att])
	}
	$targetPath = Join-Path -Path $target -ChildPath $_.Name
	$xml.Save($targetPath)
	Write-Host " saved as '$($targetPath)'"
}

Open in new window

Thank you oBdA, I will test it and let you know.
oBdA, I tested and it works for some files, for other I got the following:

+         $nodePath.SetAttribute($att, $attributes[$att])
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

Open in new window


Probably because they don't have the same structure.

Possible to add a log file to identify the files which are related to the error?

Thank you for your help.
$source = 'C:\Temp\Source'
$target = 'C:\Temp\Target'
$attributes = @{
	'style' = "fill: #888"
}
$logFile = 'C:\Temp\svg.log'
Get-ChildItem -Path $source -Filter *.svg | ForEach-Object {
	Write-Host "Processing '$($_.Name)' ..." -NoNewline
	$xml = [xml](Get-Content -Path $_.FullName)
	$nsMgr = [System.Xml.XmlNamespaceManager]$xml.NameTable
	$nsMgr.AddNamespace('s', $xml.svg.xmlns)
	If ($nodePath = $xml.SelectSingleNode('s:svg/s:path', $nsMgr)) {
		ForEach ($att in $attributes.Keys) {
			$nodePath.SetAttribute($att, $attributes[$att])
		}
		$targetPath = Join-Path -Path $target -ChildPath $_.Name
		$xml.Save($targetPath)
		Write-Host " saved as '$($targetPath)'"
	} Else {
		Write-Host " XPath 'svg/path' not found!" -ForegroundColor Yellow
		"'$($_.FullName)': XPath 'svg/path' not found!" | Add-Content -Path $logFile
	}
}

Open in new window

Thank you for this version, I was able to identify some issues, but they are related to the specs that I made:

The following file hasn't been modified:

<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<svg version="1.1" id="ICON" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1024 1024" style="enable-background:new 0 0 1024 1024;" xml:space="preserve">
<title>icons</title>
[b]<path d=[/b]"M434,629.9c6.8-210.8,207.4-180,207.4-298.5c0-65-46.8-107.1-128.7-107.1c-108.4,0-151.6,74.1-161.9,144.7  c-1.1,3.5-79.8,1.2-79.8-60.3c0-68.5,75.3-180.1,243.9-180.1C663,128.5,753,209.4,753,322.3c0,186.8-219.9,160.6-224.4,321.3  c-2.4,17.1-20.5,25.1-46.8,25.1C453.3,668.7,432.8,656.2,434,629.9z" style="fill: #888" />
[b]<path d[/b]="M484.2,763.2c-18.7,0-34.5,6.4-47.3,19.3s-19.3,28.5-19.3,46.8c0,21,6.7,37.4,20.1,49.1c13,11.5,29.9,17.8,47.3,17.6  c17.2,0.2,33.9-6.2,46.6-17.8c13.3-11.8,20-28.1,20-48.8c0-18.4-6.6-34-19.8-46.8C518.7,769.6,502.8,763.2,484.2,763.2z" />
</svg>

Open in new window


1.Issue partial replacement if <path exist multiple times.

And:
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1024 1024" style="enable-background:new 0 0 1024 1024;" xml:space="preserve">
<g id="icons">
	<g>
		<path d="M877.6,164.9c0-0.7,0-1.4-0.1-2c0-0.3-0.1-0.6-0.1-1c-0.1-0.4-0.1-0.7-0.2-1.1c-0.1-0.4-0.2-0.7-0.3-1.1    c-0.1-0.3-0.2-0.6-0.2-1c-0.1-0.3-0.2-0.7-0.4-1c-0.1-0.3-0.2-0.6-0.4-1c-0.1-0.3-0.3-0.6-0.4-0.9c-0.2-0.3-0.3-0.7-0.5-1    s-0.3-0.6-0.5-0.9c-0.2-0.3-0.4-0.6-0.6-0.9c-0.2-0.3-0.4-0.6-0.7-0.9c-0.2-0.3-0.4-0.5-0.6-0.8c-0.4-0.5-0.9-1-1.4-1.5    c0,0,0,0,0-0.1l0,0c-0.5-0.5-1-0.9-1.5-1.4c-0.3-0.2-0.5-0.4-0.8-0.6c-0.3-0.2-0.6-0.5-0.9-0.7c-0.3-0.2-0.6-0.4-0.9-0.6    c-0.3-0.2-0.6-0.3-0.9-0.5c-0.3-0.2-0.7-0.3-1-0.5c-0.3-0.1-0.6-0.3-0.9-0.4c-0.3-0.1-0.6-0.2-1-0.4c-0.3-0.1-0.7-0.3-1-0.4    c-0.3-0.1-0.7-0.2-1-0.3c-0.4-0.1-0.7-0.2-1.1-0.3c-0.4-0.1-0.8-0.1-1.1-0.2c-0.3,0-0.6-0.1-0.9-0.1c-0.7-0.1-1.4-0.1-2.1-0.1    H623.9c-11.9,0-21.5,9.6-21.5,21.5s9.6,21.5,21.5,21.5h180.3L571.8,418.9c-8.4,8.4-8.4,22,0,30.4c4.2,4.2,9.7,6.3,15.2,6.3    s11-2.1,15.2-6.3l232.4-232.4v175.4c0,11.9,9.6,21.5,21.5,21.5s21.5-9.6,21.5-21.5V164.9C877.6,165,877.6,164.9,877.6,164.9z" />
		<g>
			<path d="M741.9,881.9H169.4c-11.9,0-21.5-9.6-21.5-21.5V287.9c0-11.9,9.6-21.5,21.5-21.5h386.2c11.9,0,21.5,9.6,21.5,21.5     s-9.6,21.5-21.5,21.5H190.9v529.5h529.5V462.4c0-11.9,9.6-21.5,21.5-21.5s21.5,9.6,21.5,21.5v398[b]     [/b]C763.4,872.3,753.8,881.9,741.9,881.9z" />
		</g>
	</g>
</g>
</svg>

Open in new window

2.Issue multiple spaces at <path line 6 and 8


Is there a solution to manage those 2 cases?
ASKER CERTIFIED SOLUTION
Avatar of oBdA
oBdA

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Tested and it works! Thank you very much for your help.