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/a381802920158308/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