File System - Clean Directory

Octopus.Script exported 2014-08-20 by bobjwalker belongs to ‘File System’ category.

Clean out unwanted files from the installation directory after a deployment.

Parameters

When steps based on the template are included in a project’s deployment process, the parameters below can be set.

Paths to clean

PathsToClean

A semicolon-separated list of paths to clean.

Usually you would set this to Octopus.Action[StepName].Output.Package.InstallationDirectoryPath.

Files to remove

CleanInclude =

A semicolon-separated list of path expressions that match files to be removed.

Examples:

- *.jpg
- web.*.config
- **\*.dll
- \Logs\**\*.txt
- web.*.config;*.txt

\**\ denotes a recursive search

Files to ignore

CleanIgnore

A semicolon-separated list of path expressions that will be not be removed.

Examples:

- web.log4net.config
- img\needed.jpg
- **\*.dll
- web.config;Release Notes.txt

\**\ denotes a recursive search

Script body

Steps based on this template will execute the following PowerShell script.

# Running outside octopus
param(
	[string]$cleanInclude,
	[string]$cleanIgnore,
	[string]$pathsToClean,
	[switch]$whatIf
) 

function ExpandPathExpressions($workingDirectory, $fileExpressionList) {
	return @($fileExpressionList.Split(@(";"), "RemoveEmptyEntries")) | 
	% { $_.Trim() } |
	% { ExpandPathExpression $workingDirectory $_ }
}

function ExpandPathExpression($workingDirectory, $FileExpression) {

	# \**\ denotes a recursive search
	$recurse = "**"

	# Scope the clean!
	$fileExpression = Join-Path $workingDirectory $fileExpression

	$headSegments = Split-Path $fileExpression
	$lastSegment = Split-Path $fileExpression -Leaf
	$secondLastSegment = $(if($headSegments -ne "") {Split-Path $headSegments -Leaf} else {$null}) 

	$path = "\"
	$recursive = $false
	$filter = "*"
	
	if ($lastSegment -eq $recurse) {	
	
		$path = $headSegments
		$recursive = $true
		
	} elseif ($secondLastSegment -eq $recurse) {
		
		$path = Split-Path $headSegments
		$recursive = $true
		$filter = $lastSegment	
	
	} else {
		
		$path = $headSegments
		$filter = $lastSegment 
	}

	return Get-ChildItem -Path $path -Filter $filter -Recurse:$recursive | ? { !$_.PSIsContainer }
}

function GetParam($Name, [switch]$Required) {
	$result = $null
	
	if ($OctopusParameters -ne $null) {
		$result = $OctopusParameters[$Name]
	}

	if ($result -eq $null) {
		$variable = Get-Variable $Name -EA SilentlyContinue	
		if ($variable -ne $null) {
			$result = $variable.Value
		}
	}
	
	if ($Required -and $result -eq $null) {
		throw "Missing parameter value $Name"
	}
	
	return $result
}

& {
	param(
		[string]$cleanInclude,
		[string]$cleanIgnore,
		[string]$pathsToClean
	) 

	Write-Host "Cleaning files from installation directory"
	Write-Host "Include: $cleanInclude"
	Write-Host "Ignore: $cleanIgnore"
	Write-Host "Paths To Clean: $pathsToClean"
	
	if (!$cleanInclude) {
		throw "You must specify files to include"
	}
	
	if (!$pathsToClean) {
		throw "You must specify the paths to clean"
	}
	
	$paths = @($pathsToClean.Split(@(";"), "RemoveEmptyEntries")) | 
	% { $_.Trim() }
	
	foreach ($pathToClean in $paths) {
		
		if (Test-Path $pathToClean) {
			Write-Host "Scanning directory $pathToClean"
			
			if ($pathToClean -eq "\" -or $pathToClean -eq "/") {
				throw "Cannot clean root directory"
			}
			
			cd $pathToClean
			
			$include = ExpandPathExpressions $pathToClean $cleanInclude
			$exclude = ExpandPathExpressions $pathToClean $cleanIgnore
			
			if ($include -eq $null -or $exclude -eq $null) {
				$deleteSet = $include
			} else {
				$exclude = $exclude | % {$_}
				$deleteSet = Compare-Object $include $exclude | ? { $_.SideIndicator -eq "<=" } | % { $_.InputObject }
			}
			
			if (!$deleteSet -or $deleteSet.Count -eq 0) {
				Write-Warning "There were no files matching the criteria"
			} else {
				
				Write-Host "Deleting files"
				if ($whatIf) {
					Write-Host "What if: Performing the operation `"Remove File`" on targets"
				}
				
				$deleteSet | Write-Host
				
				if (!$whatIf) {
					$deleteSet | % { $_.FullName } | Remove-Item -Force -Recurse -WhatIf:$whatIf
				}
			}
		
		} else {
			
			Write-Warning "Could not locate path `"$pathToClean`""
		}
	}
 } `
 (GetParam 'CleanInclude' -Required) `
 (GetParam 'CleanIgnore') `
 (GetParam 'PathsToClean')
 

Provided under the Apache License version 2.0.

Report an issue

To use this template in Octopus Deploy, copy the JSON below and paste it into the Library → Step templates → Import dialog.

{
  "Id": "e56aafe2-0d59-453b-9449-d7384914468d",
  "Name": "File System - Clean Directory",
  "Description": "Clean out unwanted files from the installation directory after a deployment.",
  "Version": 27,
  "ExportedAt": "2014-08-20T06:59:52.579+00:00",
  "ActionType": "Octopus.Script",
  "Author": "bobjwalker",
  "Parameters": [
    {
      "Name": "PathsToClean",
      "Label": "Paths to clean",
      "HelpText": "A semicolon-separated list of paths to clean.\n\nUsually you would set this to `Octopus.Action[StepName].Output.Package.InstallationDirectoryPath`.",
      "DefaultValue": null,
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Name": "CleanInclude",
      "Label": "Files to remove",
      "HelpText": "A semicolon-separated list of path expressions that match files to be removed.\n\nExamples:  \n\n    - *.jpg\n    - web.*.config\n    - **\\*.dll\n    - \\Logs\\**\\*.txt\n    - web.*.config;*.txt\n\n`\\**\\` denotes a recursive search",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Name": "CleanIgnore",
      "Label": "Files to ignore",
      "HelpText": "A semicolon-separated list of path expressions that will be not be removed.\n\nExamples:  \n\n    - web.log4net.config\n    - img\\needed.jpg\n    - **\\*.dll\n    - web.config;Release Notes.txt\n\n`\\**\\` denotes a recursive search",
      "DefaultValue": null,
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    }
  ],
  "Properties": {
    "Octopus.Action.Script.ScriptBody": "# Running outside octopus\nparam(\n\t[string]$cleanInclude,\n\t[string]$cleanIgnore,\n\t[string]$pathsToClean,\n\t[switch]$whatIf\n) \n\nfunction ExpandPathExpressions($workingDirectory, $fileExpressionList) {\n\treturn @($fileExpressionList.Split(@(\";\"), \"RemoveEmptyEntries\")) | \n\t% { $_.Trim() } |\n\t% { ExpandPathExpression $workingDirectory $_ }\n}\n\nfunction ExpandPathExpression($workingDirectory, $FileExpression) {\n\n\t# \\**\\ denotes a recursive search\n\t$recurse = \"**\"\n\n\t# Scope the clean!\n\t$fileExpression = Join-Path $workingDirectory $fileExpression\n\n\t$headSegments = Split-Path $fileExpression\n\t$lastSegment = Split-Path $fileExpression -Leaf\n\t$secondLastSegment = $(if($headSegments -ne \"\") {Split-Path $headSegments -Leaf} else {$null}) \n\n\t$path = \"\\\"\n\t$recursive = $false\n\t$filter = \"*\"\n\t\n\tif ($lastSegment -eq $recurse) {\t\n\t\n\t\t$path = $headSegments\n\t\t$recursive = $true\n\t\t\n\t} elseif ($secondLastSegment -eq $recurse) {\n\t\t\n\t\t$path = Split-Path $headSegments\n\t\t$recursive = $true\n\t\t$filter = $lastSegment\t\n\t\n\t} else {\n\t\t\n\t\t$path = $headSegments\n\t\t$filter = $lastSegment \n\t}\n\n\treturn Get-ChildItem -Path $path -Filter $filter -Recurse:$recursive | ? { !$_.PSIsContainer }\n}\n\nfunction GetParam($Name, [switch]$Required) {\n\t$result = $null\n\t\n\tif ($OctopusParameters -ne $null) {\n\t\t$result = $OctopusParameters[$Name]\n\t}\n\n\tif ($result -eq $null) {\n\t\t$variable = Get-Variable $Name -EA SilentlyContinue\t\n\t\tif ($variable -ne $null) {\n\t\t\t$result = $variable.Value\n\t\t}\n\t}\n\t\n\tif ($Required -and $result -eq $null) {\n\t\tthrow \"Missing parameter value $Name\"\n\t}\n\t\n\treturn $result\n}\n\n& {\n\tparam(\n\t\t[string]$cleanInclude,\n\t\t[string]$cleanIgnore,\n\t\t[string]$pathsToClean\n\t) \n\n\tWrite-Host \"Cleaning files from installation directory\"\n\tWrite-Host \"Include: $cleanInclude\"\n\tWrite-Host \"Ignore: $cleanIgnore\"\n\tWrite-Host \"Paths To Clean: $pathsToClean\"\n\t\n\tif (!$cleanInclude) {\n\t\tthrow \"You must specify files to include\"\n\t}\n\t\n\tif (!$pathsToClean) {\n\t\tthrow \"You must specify the paths to clean\"\n\t}\n\t\n\t$paths = @($pathsToClean.Split(@(\";\"), \"RemoveEmptyEntries\")) | \n\t% { $_.Trim() }\n\t\n\tforeach ($pathToClean in $paths) {\n\t\t\n\t\tif (Test-Path $pathToClean) {\n\t\t\tWrite-Host \"Scanning directory $pathToClean\"\n\t\t\t\n\t\t\tif ($pathToClean -eq \"\\\" -or $pathToClean -eq \"/\") {\n\t\t\t\tthrow \"Cannot clean root directory\"\n\t\t\t}\n\t\t\t\n\t\t\tcd $pathToClean\n\t\t\t\n\t\t\t$include = ExpandPathExpressions $pathToClean $cleanInclude\n\t\t\t$exclude = ExpandPathExpressions $pathToClean $cleanIgnore\n\t\t\t\n\t\t\tif ($include -eq $null -or $exclude -eq $null) {\n\t\t\t\t$deleteSet = $include\n\t\t\t} else {\n\t\t\t\t$exclude = $exclude | % {$_}\n\t\t\t\t$deleteSet = Compare-Object $include $exclude | ? { $_.SideIndicator -eq \"<=\" } | % { $_.InputObject }\n\t\t\t}\n\t\t\t\n\t\t\tif (!$deleteSet -or $deleteSet.Count -eq 0) {\n\t\t\t\tWrite-Warning \"There were no files matching the criteria\"\n\t\t\t} else {\n\t\t\t\t\n\t\t\t\tWrite-Host \"Deleting files\"\n\t\t\t\tif ($whatIf) {\n\t\t\t\t\tWrite-Host \"What if: Performing the operation `\"Remove File`\" on targets\"\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t$deleteSet | Write-Host\n\t\t\t\t\n\t\t\t\tif (!$whatIf) {\n\t\t\t\t\t$deleteSet | % { $_.FullName } | Remove-Item -Force -Recurse -WhatIf:$whatIf\n\t\t\t\t}\n\t\t\t}\n\t\t\n\t\t} else {\n\t\t\t\n\t\t\tWrite-Warning \"Could not locate path `\"$pathToClean`\"\"\n\t\t}\n\t}\n } `\n (GetParam 'CleanInclude' -Required) `\n (GetParam 'CleanIgnore') `\n (GetParam 'PathsToClean')\n ",
    "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-clean-directory.json",
  "Website": "/step-templates/e56aafe2-0d59-453b-9449-d7384914468d",
  "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"
  }
}

History

Page updated on Wednesday, August 20, 2014