Luis Diaz
asked on
Windows Batch & Powershell & VBS Script: add text in between
Hello experts,
I have the following SVG file.
The idea is to read all SVG files located in specific folder and generate new version in another folder with the following structure:
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.
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>
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>
1.The script should addstyle="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.
So if there is currently anything between those two match strings, it should be removed and replaced with the string to insert?
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.
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.
ASKER
Probably this can help us:
Powershell:
Windows batch: based on Control.txt
If you have a best proposal please let me know.
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
}
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
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.
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)'"
}
ASKER
Thank you oBdA, I will test it and let you know.
ASKER
oBdA, I tested and it works for some files, for other I got the following:
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.
+ $nodePath.SetAttribute($att, $attributes[$att])
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
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
}
}
ASKER
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:
1.Issue partial replacement if <path exist multiple times.
And:
Is there a solution to manage those 2 cases?
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>
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>
2.Issue multiple spaces at <path line 6 and 8Is there a solution to manage those 2 cases?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Tested and it works! Thank you very much for your help.