Andrew Beaumont
Andrew Beaumont

Reputation: 35

Using Variable in Remove-Item returns "A drive with the name '"E' does not exist"

I have been writing a script which searches for specific folders within an "Archive" folder and then zips them. Once the folder is successfully zipped I would like it to be deleted.

However, I am running into an issue where the Remove-Item cmdlet is returning the error "A drive with the name '"E' does not exist" when I use the foreach command and a variable.

If I run the Remove-Item command manually with the variable the issue does not occur.

Please let me know why this is happening and what I can do to stop it from happening.

Here is the code:

# Get list of archive folders
$ArchiveFolders = Get-ChildItem \*\*\* |
                  ?{ $_.PSIsContainer } |
                  Where-Object{ $_.Name -eq "_Archived"} | select FullName

# For each archive folder check which subfolders exist within it
foreach ($folder in $ArchiveFolders) {
  (Get-ChildItem $folder.FullName | ?{ $_.PSIsContainer } | select FullName | ConvertTo-Csv -NoTypeInformation) |
    Select-Object -Skip 1 |
    Add-Content -Path e:\scripts\subfolders.csv
}

# Get list of Subfolders
$ArchiveSubFolders = Get-Content e:\scripts\subfolders.csv

# Select each Subfolder
foreach ($subfolder in $ArchiveSubFolders){
  # Move each subfolder to a 7z Archive with the highest compression rate available
  $pinfo = New-Object System.Diagnostics.ProcessStartInfo
  $pinfo.FileName = "7z.exe"
  $pinfo.RedirectStandardError = $true
  $pinfo.RedirectStandardOutput = $true
  $pinfo.UseShellExecute = $false
  $pinfo.Arguments = "a -mx=9 -t7z $subfolder.7z $subfolder"
  $p = New-Object System.Diagnostics.Process
  $p.StartInfo = $pinfo
  $p.Start() | Out-Null
  $p.WaitForExit()

  # Check Archive was created successfully and then delete the subfolder
  if ($p.ExitCode -eq "0") {
    Remove-Item -Path $subfolder -Force -Recurse
  } else {
    Write-Host "$subfolder has not been deleted"
  }
}

Upvotes: 2

Views: 1416

Answers (1)

Ansgar Wiechers
Ansgar Wiechers

Reputation: 200493

PowerShell CSV export/conversion adds double quotes around the fields. Since you read that CSV output via Get-Content the double quotes are preserved on import, so you get paths "E:\foo" instead of E:\foo. This might work for constructing the external command, but it does not work for PowerShell cmdlets, because there is no drive "E: (with a leading double quote). It's usually a bad idea to make quotes part of the value. You're better off leaving the values without qoutes and adding quotes where they're required.

$ArchiveSubFolders = foreach ($folder in $ArchiveFolders) {
  Get-ChildItem $folder.FullName |
    Where-Object { $_.PSIsContainer } |
    Select-Object -Expand FullName
}

With that said, you don't even need most of your code. You can get the subfolders you want by changing your original path expression to \*\*\*\_Archived\* and run a single Get-ChildItem with that. I'd also recommend dropping the System.Diagnostics.Process approach and use the call operator (&) instead.

Get-ChildItem '\*\*\*\_Archived\*' | Where-Object {
  $_.PSIsContainer
} | Select-Object -Expand FullName | ForEach-Object {
  & 7z.exe a -mx=9 -t7z "$_.7z" "$_"
  if ($LastExitCode -eq 0) {
    Remove-Item -Path $_ -Force -Recurse
  } else {
    Write-Host "$subfolder has not been deleted"
  }
}

Upvotes: 1

Related Questions