我发现了这个很棒的powershell脚本
gci -include bin,obj -recurse | remove-item -force -recurse
我每天多次使用它。
如何防止它通过任何node_modules文件夹(如果存在)或其子级运行?
我尝试过
的各种版本gci -exclude node_modules -include bin,obj -recurse | remove-item -force -recurse
没有成功。
更新: 阅读@ HAL9256的翔实答案后,我意识到我未能包括一项重要要求。我在git repo的根目录下运行此脚本。因此,它将遍历多个C#项目文件夹,从而删除所有文件夹的bin和obj文件夹。这仅是必需的,因为Visual Studio 2017和2019解决方案清理不会删除所有内容,并且由于我们正在从框架转换为标准/核心的过程中,因此清理后会在bin和/或obj文件夹中留下一些工件,从而导致问题通过git分支更改在转换给定项目(可能从内核回框架)时中断。
答案 0 :(得分:0)
此问题的根源是滥用递归与过滤相结合。我将通过一些示例进行说明。首先,我们应该建立一个示例目录结构:
mkdir Temp
mkdir Temp\bin
mkdir Temp\obj
mkdir Temp\node_modules
mkdir Temp\node_modules\bin
mkdir Temp\node_modules\obj
Out-File .\Temp\Readme.md
Out-File .\Temp\bin\Readme.md
Out-File .\Temp\obj\Readme.md
Out-File .\Temp\node_modules\Readme.md
Out-File .\Temp\node_modules\bin\Readme.md
Out-File .\Temp\node_modules\obj\Readme.md
cd .\Temp\
让我们尝试一些示例。我将把Get-ChildItem
的内容传送到Select-Object
中,以更好地说明我们要检索的内容。首先,香草Get-ChildItem
:
PS C:\Temp> Get-ChildItem | Select-Object FullName
FullName
--------
C:\Temp\bin
C:\Temp\node_modules
C:\Temp\obj
C:\Temp\Readme.md
这将返回我们期望的值,相当于dir
。现在,让我们尝试-Include
仅“包含” bin
文件夹。
PS C:\Temp> Get-ChildItem -Include bin | Select-Object FullName
PS C:\Temp>
嗯。它什么也没返回。。。我们以为它将得到所有内容的列表,并且“仅”包括bin文件夹。相反,它所做的是将命令解释为“无”的Get-ChildItem
,(因为我们未指定要获取的任何文件),将“无”的“ Include”解释为模式{{1} }。这很有意义,并在Docs中列出了“包含需要Path参数”。好。让我们对其进行更改,以使所有内容bin
然后执行*
,然后,我们应该得到想要的...对吗?
-Include bin
Hu?我以为通配符会包含PS C:\Temp> Get-ChildItem * -Include bin | Select-Object FullName
PS C:\Temp>
文件夹,对吗?那不是它的工作原理吗?让我们将其更改为bin
文件而不是目录:
-Include
所以看起来像是显式过滤,带通配符的是文件,而不是目录。那么,其中包含目录的原始示例如何工作?...这是因为PS C:\Temp> Get-ChildItem * -Include Readme.md | Select-Object FullName
FullName
--------
C:\Temp\Readme.md
的工作原理不同。 -Recurse
改变了我们得到的东西,它返回了一切,因此-Recurse
可以工作:
Include
在此示例中,当我们不必指定通配符PS C:\Temp> Get-ChildItem -Include bin -Recurse | Select-Object FullName
FullName
--------
C:\Temp\bin
C:\Temp\node_modules\bin
过滤器时,*
隐式地从目录中获取所有内容。注意:它包含与名称-Recurse
匹配的目录。另外,请注意,它不包含目录内的文件。
为什么示例1:
bin
之所以可行,是因为gci -include bin,obj -recurse | remove-item -force -recurse
返回目录,而Get-ChildItem
和Remove-Item
和-Force
则负责删除文件。
要证明没有什么时髦的事,让我们做一个-Recurse
:
-Exclude node_modules
好吧……回报率超出了预期……但没有。请注意,它没有返回PS C:\Temp> Get-ChildItem -Exclude node_modules -Recurse | Select-Object FullName
FullName
--------
C:\Temp\bin
C:\Temp\bin\Readme.md
C:\Temp\node_modules\bin
C:\Temp\node_modules\bin\Readme.md
C:\Temp\node_modules\obj
C:\Temp\node_modules\obj\Readme.md
C:\Temp\node_modules\Readme.md
C:\Temp\obj
C:\Temp\obj\Readme.md
C:\Temp\Readme.md
。这是因为C:\Temp\node_modules
是正确的。它排除了专门命名为-Exclude node_modules
的文件夹,并包括了其他所有内容。
这是第二个示例不起作用的原因:
node_modules
排除过滤器将排除名为gci -exclude node_modules -include bin,obj -recurse | remove-item -force -recurse
的特定文件夹,但是由于node_modules
将-Recurse
匹配-Include
或bin
的所有子文件夹。当然,obj
中的哪个 吨很多,因此无法按我们的意愿工作。
因此,如果node_modules
不适用于目录,并且-Include
太深,那么什么将解决@cResults问题?好吧,为什么不摆弄过滤器,我们为什么不只是简单地索要我们想要的文件夹呢?
-Recurse
这没关系,它返回了文件夹的内容,就像前面的示例一样,子项而不是目录...好吧,我们确实想要的是文件夹项,因此我们使用PS C:\Temp> Get-ChildItem bin,obj | Select-Object FullName
FullName
--------
C:\Temp\bin\Readme.md
C:\Temp\obj\Readme.md
代替Get-ChildItem
:
Get-Item
现在,切换到PS C:\Temp> Get-Item bin,obj | Select-Object FullName
FullName
--------
C:\Temp\bin
C:\Temp\obj
,我们得到的是文件夹,而不是文件夹中的子项,我们现在可以将其与Get-Item
一起使用,剩下的工作就可以了:
Remove-Item
答案 1 :(得分:0)
对于任何正在寻找的人,就像我刚才一样,这里有一个完整的解决方案。
使用 Lee_Dailey 建议的 Where-Object
,您可以在递归后排除 node_modules
目录。
gci -include bin,obj -recurse | where-object {$_.FullName -notlike '*\node_modules*'} | remove-item -force -recurse