【问题标题】:Delete all files and folders but exclude a subfolder删除所有文件和文件夹,但排除子文件夹
【发布时间】:2021-10-07 16:30:21
【问题描述】:

我有一个文件夹,我需要删除除一小部分文件和文件夹之外的所有文件和文件夹。

我已经可以排除文件列表,但看不到排除文件夹及其内容的方法。

这是文件夹结构:

|-C:\temp
 \-C:\temp\somefile.txt
 \-C:\temp\someotherfile.txt
| |-C:\temp\foldertodelete
   \-C:\temp\foldertodelete\file1.txt
| |-C:\temp\foldertokeep
|  \-C:\temp\foldertokeep\file2.txt

我想保留 somefile.txt 和文件夹 foldertokeep 及其内容。

这就是我现在拥有的:

Get-ChildItem -Path  'C:\temp' -Recurse -exclude somefile.txt | Remove-Item -force -recurse

这确实不会删除 somefile.txt。有没有办法从删除列表中排除文件夹 foldertokeep 及其内容?

【问题讨论】:

  • 我在这里缺少什么?这似乎对我有用Get-ChildItem -Path 'C:\temp' -Recurse -exclude somefile.txt, foldertokeep | Remove-Item -force -recurse

标签: powershell


【解决方案1】:
Get-ChildItem -Path  'C:\temp' -Recurse -exclude somefile.txt |
Select -ExpandProperty FullName |
Where {$_ -notlike 'C:\temp\foldertokeep*'} |
sort length -Descending |
Remove-Item -force 

-recurse 开关在 Remove-Item 上不能正常工作(它会在文件夹中的所有子项目都被删除之前尝试删除文件夹)。按长度降序对全名进行排序可确保在删除文件夹中的所有子项之前没有删除任何文件夹。

【讨论】:

  • 复杂而精彩,典型的 Powershell 粗糙。我希望它不断发展。谢谢。
  • 我必须在最后一行添加一个额外的 [-Recurse] 参数才能让脚本在没有提示的情况下继续运行。
  • sort length -Descending 在做什么?
  • 按全名字符串的长度对文件和目录全名进行降序排序。这样可以确保在删除目录的所有子项之前,它不会尝试删除目录。
【解决方案2】:

在 PowerShell 3.0 和以下中,您可以尝试简单地这样做:

Remove-Item -recurse c:\temp\* -exclude somefile.txt,foldertokeep

除非我缺少某些参数,否则这似乎可以解决问题...

编辑:见下面的 cmets,PS3 之后 Remove-Item 的行为发生了变化,这个解决方案似乎不再适用了。

【讨论】:

  • 我在 PowerShell 3.0 中执行此操作,效果很好。但是,我只是注意到 PowerShell 4.0 中的行为发生了变化。例如,假设您在同一父目录中有目录“a”和“b”,并且在目录“a”下有文件“c.txt”。如果您从父目录运行“rm .\* -Recurse -Exclude a”。在 PS 4 中,c.txt 将被删除。在 PS 3 中不会。我想知道这是否是 PS 4 中的错误,因为它没有意义恕我直言。
  • @JonMiller 这里有同样的问题。从 PS2 迁移到 PS4 后,我们注意到一些重要目录已从我们的一个系统中删除。备份的好东西。 :)
  • cmets 中的重要信息。因此,根据 PowerShell 版本的不同,考虑到不同的可能行为,这可能不是一种安全的技术?
  • 哈哈。它尊重排除文件夹,但可惜不是它的内容
  • 刚刚又看了一遍。它看起来比@JonMiller 提到的还要糟糕。根据我的实验,-exclude 仅在使用-recurse 时应用于根目录。这绝对看起来像一个错误......编辑:没关系,它比那更奇怪。
【解决方案3】:

选择除需要保留的内容之外的所有内容并将其传递给删除命令。

假设你有那些文件夹

C:.
├───delme1
│   │   delme.txt
│   │
│   └───delmetoo
├───delme2
├───keepme1
│       keepmetoo.txt
│
└───keepme2

删除所有内容,但保留 keepme1 和 keepme2 文件夹。

Get-ChildItem -Exclude keepme1,keepme2 | Remove-Item -Recurse -Force

其他解决方案很好,但我发现这很容易理解和记住。

【讨论】:

  • 我喜欢这个解决方案,不过你只需要一个递归:Get-ChildItem -Exclude folder1,folder2 | Remove-Item -Recurse -Force
  • 真的@AxelWass,比XD更好的解决方案
【解决方案4】:

我使用了以下内容,只是从第一行中删除了 -Recurse,它将所有文件和子文件夹留在了排除文件夹列表下。

   Get-ChildItem -Path "PATH_GOES_HERE" -Exclude "Folder1", "Folder2", "READ ME.txt" | foreach ($_) {
       "CLEANING :" + $_.fullname
       Remove-Item $_.fullname -Force -Recurse
       "CLEANED... :" + $_.fullname
   }

【讨论】:

    【解决方案5】:

    是的,我知道这是一个旧线程。我无法在 Powershell 5 中获得上述任何答案,所以这是我想出的:

    Get-ChildItem -Path $dir -Exclude 'name_to_ignore' |
    ForEach-Object {Remove-Item $_ -Recurse }
    

    这会将 -Recurse 移动到 Remove-Item 而不是找到项目的位置。

    【讨论】:

      【解决方案6】:

      根据MSDNRemove-Item-exclude 参数存在一个已知问题。请改用此变体。

      Get-ChildItem * -exclude folderToExclude | Remove-Item
      

      【讨论】:

      • 注意:<folderToExclude> 只能是 folderToExclude 的名称,不能以 \* 结尾,否则它将在第一级留下空目录(仅限,不能超过)
      【解决方案7】:

      这也会对某人有所帮助...

      为 PATH_GOES_HERE 添加一个空的或之前未定义的变量可能会导致用户目录(或 C:\windows\system32,如果脚本以管理员身份运行)中的递归删除。我发现这很困难,不得不重新安装 Windows。

      自己试试吧! (下面只会将文件目录输出到test.txt)

      Get-ChildItem -Path $dir2 -Recurse -Exclude "Folder1 ", FileName.txt | foreach ($_) {
      $_.fullname >> C:\temp\test.txt
      }
      

      【讨论】:

        【解决方案8】:

        我遇到了这个问题,发现了一个适合我的单行命令。它将删除相关目录中的所有文件夹和文件,同时保留“排除”列表中的任何内容。它也是无声的,因此如果某些文件是只读的或正在使用的,它不会返回错误。

        @powershell Remove-item C:\Random\Directory\* -exclude "MySpecialFolder", "MySecondSpecialFolder" -force -erroraction 'silentlycontinue'
        

        【讨论】:

          【解决方案9】:

          我用过这个,非常适合我

          Get-ChildItem -Path 'C:\Temp\*' -Recurse | Where-Object {($_.FullName -notlike "*windirstat*") -and ($_.FullName -notlike "C:\Temp\GetFolderSizePortable*")} | Remove-Item -Recurse
          

          【讨论】:

            【解决方案10】:

            如果您的路径包含正则表达式特殊字符,那么您需要使用不允许管道的 -LiteralPath 选项。在这种情况下,正确的解决方案如下所示:

                Remove-Item -force -LiteralPath(    
                Get-ChildItem -Path  'C:\temp' -Recurse -exclude somefile.txt |
                Select-Object -ExpandProperty FullName |
                Where-Object { $_ -notlike 'C:\temp\foldertokeep*' } |
                Sort-Object length -Descending 
            ) 
            

            【讨论】:

              【解决方案11】:

              这也会对某人有所帮助...

              Get-ChildItem -Path PATH_GOES_HERE -Recurse -Exclude "Folder1 ", "Folder2", FileName.txt | foreach ($_) {
                  "CLEANING :" + $_.fullname
                  Remove-Item $_.fullname -Force -Recurse
                  "CLEANED... :" + $_.fullname
              }
              

              【讨论】:

                【解决方案12】:

                我想为这个想法做出贡献

                • 删除所有文件夹和文件包括隐藏文件夹

                $get-childitem -Path D:\path\folder\to\delete* -Force |select-object -Expandproperty Fullname |remove-item -recurse -Confirm:$false -Force

                • 删除所有文件夹和文件包括隐藏文件夹但保留排除文件夹

                $get-childitem -Path D:\path\folder\to\delete* -Exclude nameexludefolder -Force |选择对象-Expandproperty 全名 |删除项目-强制

                $get-childitem -Path D:\path\folder\to\delete\ -Exclude nameexludefolder -Force |选择对象-Expandproperty 全名 |删除项目-强制

                第一行保留文件夹, 第二行删除剩余文件夹

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2012-04-01
                  • 2010-11-12
                  • 1970-01-01
                  • 1970-01-01
                  • 2013-02-15
                  相关资源
                  最近更新 更多