Octopus.Script exported 2014-05-14 by bobjwalker belongs to ‘File System’ category.
Find and replace text in one or more files.
Parameters
When steps based on the template are included in a project’s deployment process, the parameters below can be set.
Files
FRCandidatePathGlobs
The files to search. Wildcards *
and **
are supported. Paths must be fully-qualified, e.g. C:\MyApp\**\*.xml
. Separate multiple paths with ;
semicolons.
Find
FRFindText
The text to find in the target files.
Replace with
FRReplaceText
The replacement text to insert in place of each occurrence of Find.
Ignore case
FRIgnoreCase = False
If True, variations on the character case of Find will be considered a match, for example Bar
will match BAR
and bar
. If False only exact matches will be considered.
Script body
Steps based on this template will execute the following PowerShell script.
function Execute-FindReplace($target, $find, $replace, $ignoreCase) {
$options = [System.Text.RegularExpressions.RegexOptions]::None
if ($ignoreCase) {
$options = [System.Text.RegularExpressions.RegexOptions]::IgnoreCase
}
Write-Output "Searching $target..."
$orig = [System.IO.File]::ReadAllText($target)
$escFind = [System.Text.RegularExpressions.Regex]::Escape($find)
$regex = new-object System.Text.RegularExpressions.Regex($escFind, $options)
$removed = $regex.Replace($orig, '')
$occurrences = ($orig.Length - $removed.Length) / $find.Length
if ($occurrences -gt 0) {
Write-Output "Found $occurrences occurrence(s), replacing..."
$escReplace = $replace.Replace('$', '$$')
$replaced = $regex.Replace($orig, $escReplace)
[System.IO.File]::WriteAllText($target, $replaced)
}
}
if ([string]::IsNullOrEmpty($FRFindText)) {
throw "A non-empty 'Find' text block is required"
}
Write-Output "Replacing occurrences of '$FRFindText' with '$FRReplaceText'"
if ([Boolean] $FRIgnoreCase) {
Write-Output "Case will be ignored"
}
$FRCandidatePathGlobs.Split(";") | foreach {
$glob = $_.Trim()
Write-Output "Searching for files that match $glob..."
$matches = $null
$splits = $glob.Split(@('/**/'), [System.StringSplitOptions]::RemoveEmptyEntries)
if ($splits.Length -eq 1) {
$splits = $glob.Split(@('\**\'), [System.StringSplitOptions]::RemoveEmptyEntries)
}
if ($splits.Length -eq 1) {
$matches = ls $glob
} else {
if ($splits.Length -eq 2) {
pushd $splits[0]
$matches = ls $splits[1] -Recurse
popd
} else {
$splits
throw "The segment '**' can only appear once, as a directory name, in the glob expression"
}
}
$matches | foreach {
$target = $_.FullName
Execute-FindReplace -target $target -find $FRFindText -replace $FRReplaceText -ignoreCase ([Boolean] $FRIgnoreCase)
}
}
Write-Output "Done."
Provided under the Apache License version 2.0.
To use this template in Octopus Deploy, copy the JSON below and paste it into the Library → Step templates → Import dialog.
{
"Id": "87cbaa94-4477-4474-a9c3-7943b5668d30",
"Name": "File System - Find and Replace",
"Description": "Find and replace text in one or more files.",
"Version": 7,
"ExportedAt": "2014-05-14T05:38:42.041+00:00",
"ActionType": "Octopus.Script",
"Author": "bobjwalker",
"Parameters": [
{
"Name": "FRCandidatePathGlobs",
"Label": "Files",
"HelpText": "The files to search. Wildcards `*` and `**` are supported. Paths must be fully-qualified, e.g. `C:\\MyApp\\**\\*.xml`. Separate multiple paths with `;` semicolons.",
"DefaultValue": null,
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Name": "FRFindText",
"Label": "Find",
"HelpText": "The text to find in the target files.",
"DefaultValue": null,
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Name": "FRReplaceText",
"Label": "Replace with",
"HelpText": "The replacement text to insert in place of each occurrence of _Find_.",
"DefaultValue": null,
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Name": "FRIgnoreCase",
"Label": "Ignore case",
"HelpText": "If **True**, variations on the character case of _Find_ will be considered a match, for example `Bar` will match `BAR` and `bar`. If **False** only exact matches will be considered.",
"DefaultValue": "False",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
}
],
"Properties": {
"Octopus.Action.Script.ScriptBody": "function Execute-FindReplace($target, $find, $replace, $ignoreCase) {\n $options = [System.Text.RegularExpressions.RegexOptions]::None\n if ($ignoreCase) {\n $options = [System.Text.RegularExpressions.RegexOptions]::IgnoreCase\n }\n \n Write-Output \"Searching $target...\"\n $orig = [System.IO.File]::ReadAllText($target)\n \n $escFind = [System.Text.RegularExpressions.Regex]::Escape($find)\n $regex = new-object System.Text.RegularExpressions.Regex($escFind, $options)\n $removed = $regex.Replace($orig, '')\n \n $occurrences = ($orig.Length - $removed.Length) / $find.Length\n if ($occurrences -gt 0) {\n Write-Output \"Found $occurrences occurrence(s), replacing...\"\n \n $escReplace = $replace.Replace('$', '$$')\n $replaced = $regex.Replace($orig, $escReplace)\n [System.IO.File]::WriteAllText($target, $replaced)\n }\n}\n\nif ([string]::IsNullOrEmpty($FRFindText)) {\n throw \"A non-empty 'Find' text block is required\"\n}\n\nWrite-Output \"Replacing occurrences of '$FRFindText' with '$FRReplaceText'\"\nif ([Boolean] $FRIgnoreCase) {\n Write-Output \"Case will be ignored\"\n}\n\n$FRCandidatePathGlobs.Split(\";\") | foreach {\n $glob = $_.Trim()\n Write-Output \"Searching for files that match $glob...\"\n\n $matches = $null\n $splits = $glob.Split(@('/**/'), [System.StringSplitOptions]::RemoveEmptyEntries)\n\n if ($splits.Length -eq 1) {\n $splits = $glob.Split(@('\\**\\'), [System.StringSplitOptions]::RemoveEmptyEntries)\n }\n \n if ($splits.Length -eq 1) {\n $matches = ls $glob\n } else {\n if ($splits.Length -eq 2) {\n pushd $splits[0]\n $matches = ls $splits[1] -Recurse\n popd\n } else {\n $splits\n throw \"The segment '**' can only appear once, as a directory name, in the glob expression\"\n\n }\n }\n\n $matches | foreach {\n \n $target = $_.FullName\n\n Execute-FindReplace -target $target -find $FRFindText -replace $FRReplaceText -ignoreCase ([Boolean] $FRIgnoreCase)\n }\n}\n\n\nWrite-Output \"Done.\"",
"Octopus.Action.Script.Syntax": "PowerShell"
},
"Category": "File System",
"HistoryUrl": "https://github.com/OctopusDeploy/Library/commits/master/step-templates//opt/buildagent/work/75443764cd38076d/step-templates/file-system-find-and-replace.json",
"Website": "/step-templates/87cbaa94-4477-4474-a9c3-7943b5668d30",
"Logo": "iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAMAAACahl6sAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAKhQTFRF/////78A/6oAVVVV/++//+q/gICA1dXV/79A/9R///ff/8MQ/9dg/8cg//vv/68A/+ef//PP//rv/7Ug/68Q/+Sv/8sw/9tw/9NQ/89w/+uv/+OP/8pg/89A/8VQ/9+f/9+A/9qP/+/P/99//7cA/7IA/7wA/6sA/+/A39/f/64A2tjX//Tfn5+f/7MA/7sA/74A/60A/9Zw/7gA/74Q/7oA/7UA/7EAi6g4fwAAAuRJREFUeNrs21tT2mAUheEvaaCQQCSczyi29WzP7f//Z6UdZBIIM44us9hf13vbC+eRbLo3qnNKKaWUUkoppZRSSimllFJKKaWUwlVrLhsvbrLqnoai2+yFr2x+fwKOwasZm/oXdEczxDQnOyYhqgn3uQpxDZhz3gdCesQ3r3mIjDfwXagj7NEgKywkXLMgSzCE9mz1wBDaOzDYETYEEUSQ/wPSaz6rQa174pDnt1x5Atm8emtPIGG48gUClJAh/XtPILi36+L3Zz6oVdBF4w32/sIbYmWH6qAPX5fzjio/14Q/W7nnqtIPDnYfFfThkGpPovXu68IhNdKSVyXkoQ7qgQypvwNVFwQDuXkP6oYM8WbYBWFDYMPNHnZBTv3tV8MuiCC+Q6K36+ypkn/LsJC4lQSkhhkQch4Qa+MgrYBahIKcB35AYrIjyEAQ9gsCm5E2GTIDQabsJysFQcZkxxj0H2LKfkGmIMjM3KgfgbBHfQSCROwnKwZByNtJsACt8WlChnRAkA7ZkaAOqyEZ0gJB7O2LRyAjsmOIutlNjnoJhD3qL9gXyyFjk6N+CKGPegSC2DsNj0DY++IlCEI/DWMQhL0vjh0GYvE0LIWwT8PEgSDsfXEEgmRmR30PYvI0LIGkRvfFAwj9NExBkIXRfXEfYvQ0PISwT8O2A0HYoz4DQb4ZPQ0PID8sj3oO8tXuvliEPJoe9Rzkk9XTcA9yZnhfLEA+mD0Ni5Ar9gvSAUE+2j0Ni5DPdk/DAuTW9L6Yg7BHfehAkC/WR30LoY96CoL8tL0v7iD0fTECQX4Z3xd3EPa+OANBflvfF58g363vi1sIfV+cgiCPPoz6Xwh71EcgyK0Xo76BsPfFBcbhrjzYF/9l/zTcxj4NWyBH7Mmo038zFvWCsCHt1HnxaCWZg8X8ifQwxjlcSvsJaHLpsGW5v2S8vo4qyymF7+5O3wOllFJKKaWUUkoppZRSSimllPKxPwIMAPj2YtijZbi5AAAAAElFTkSuQmCC",
"$Meta": {
"Type": "ActionTemplate"
}
}
Page updated on Wednesday, May 14, 2014