PowerShell - As cadeias de caracteres quase equivalentes não são equivalentes?

0

Eu tenho uma string que estou passando para o meu script como argumento. No entanto, para exibir o código aqui, eu os especifiquei manualmente no código.
Essas variáveis são:

  • $SearchFolder
  • $FileType

O código é assim:

$SearchFolder = "C:\Users\Name\Downloads"
$FileType = "*.ttf"

#Trim the backslash from the end in case the user adds one in.
$SearchFolder = $SearchFolder.TrimEnd('\')
$FontPathsSearch = $SearchFolder + "\" + $FileType

#For use in debugging.
echo $SearchFolder
echo $FontPathsSearch

$folders = dir -s $FontPathsSearch | Select Directory -Unique | findstr -v -x $SearchFolder
echo $folders

Como pode ser visto, no final da última linha, estou usando findstr -v -x $SearchFolder para exibir todos os resultados que não correspondem ao diretório raiz (da pesquisa), neste caso C:\Users\Name\Downloads .

A saída, no entanto, é assim:

C:\Users\Name\Downloads
C:\Users\Name\Downloads\*.ttf

Directory 
---------    
C:\Users\Name\Downloads\FolderofFont1  
C:\Users\Name\Downloads\FolderofFont2 
C:\Users\Name\Downloads\FolderofFont3 
C:\Users\Name\Downloads          

O problema:
Como pode ser visto na saída do código, embora $SearchFolder e a última linha da saída pareçam ser as mesmas, obviamente elas não são, porque, do contrário, elas não seriam exibidas. Meus pensamentos são de que poderia haver um terminador nulo ou um fim de linha lá, mas como eu não sei como depurar usando o PowerShell, não posso ter certeza.

O que eu gostaria de saber:
Como eu seria capaz de filtrar essencialmente o diretório principal, através do método atualmente sendo utilizado (ou através de um método melhor se tal existir).

    
por Synthetic Ascension 12.07.2015 / 15:29

1 resposta

1

Parece que você está vindo para o PowerShell com um sólido histórico de CMD / Batch ou está tentando adaptar as instruções / tutoriais do CMD / Batch.

Alguns dos problemas que você pode estar percebendo é que você está tentando usar alguns comandos como se estivessem sendo executados a partir do prompt de comando em vez do PowerShell. O que quero dizer com isso é que, no PowerShell, dir não executa o comando dir mas é um alias para um cmdlet do PowerShell Get-ChildItem

É por isso que usar /s não funciona e os cmdlets do PowerShell não usam sinalizadores '/', mas sim '-' parameters

Como a equipe do PowerShell sabia que as pessoas usariam dir com a opção / s, eles adicionaram s como um alias para o parâmetro -Recurse , e é por isso que essa parte do comando funciona.

Desculpe-me por falar sobre isso, mas percebi que alguns antecedentes podem ser relevantes.

Para o problema em si. O PowerShell está trabalhando com objetos e está passando seus objetos pelo pipeline até finalmente gerar os objetos para o console.

O comando findstr está tentando operar em seqüências de caracteres (e não tenho 100% de certeza se ele funcionará na entrada do pipeline do PowerShell se você reduzi-lo a apenas sequências de caracteres).

Sugiro não usar o comando e, em vez disso, use o Where-Object (ou mais simplesmente seu alias Onde )

O primeiro instinto é fazer isso:

| Where -FilterScript { $_.Directory -ne $SearchFolder }
# (Directory property 'Not Equal' variable)

Mas o que você vai descobrir é que na verdade existem mais dados armazenados na propriedade Directory do que o que você vê quando é gravado no console.

Name        MemberType   Definition                                                                             
----        ----------   ----------                         
Directory   NoteProperty DirectoryInfo Directory=C:\Users\name\Downloads\FolderofFont1

Existem duas opções para contabilizar esses dados extras, use um curinga:

| Where -FilterScript { $_.Directory -notlike "*$SearchFolder" }
# (Directory property 'Not Like' variable with a wildcard)

ou teste uma propriedade diferente, que é apenas a string nas perguntas:

| Where -FilterScript { $_.DirectoryName -ne $SearchFolder }
# (Directory Name property 'Not Equal' variable)

No entanto, se você usar a abordagem DirectoryName, precisará colocá-la antes da instrução Select, pois essa propriedade não estará disponível se você já tiver limitado o objeto apenas ao diretório.

Este é o resultado final:

...
$folders = Get-ChildItem -Path $FontPathsSearch -Recurse | Select Directory -Unique | Where -FilterScript { $_.Directory -notlike "*$SearchFolder" }
$folders

Directory                                                                                          
---------                                                                                          
C:\Users\name\Downloads\bootstrap-3.3.4-dist\bootstrap\fonts                                    
C:\Users\name\Downloads\dashboards-gh-pages\dashboards-gh-pages\assets\lib\bootstrap\dist\fonts 
C:\Users\name\Downloads\dashboards-gh-pages\dashboards-gh-pages\assets\lib\bootstrap\fonts      
C:\Users\name\Downloads\klimato-dashing-widget-master\klimato-dashing-widget-master\assets\fonts
C:\Users\name\Downloads\solar-theme-jekyll-master\solar-theme-jekyll-master\assets\fonts 

Sinto muito que a resposta tenha sido muito mais longa do que eu pretendia, espero que faça sentido. Eu imaginei dar algum contexto e como e por que de tudo isso iria um pouco além de apenas "Aqui está um trecho de código que funcionará para você".

Além disso, sinto-me obrigado a mencionar que no PowerShell echo é um alias para Write-Host , que é considerado prática ruim . Obviamente, é útil para suas informações de depuração, mas quando se trata de retornar os resultados, você pode simplesmente chamar a variável.

Isso remete ao PowerShell sendo tudo sobre objetos. Retornar o objeto (especialmente como parte de uma função) significa que você pode continuar agindo nos dados como um objeto, no entanto, se você executá-lo através do Write-Host, ele será convertido em uma string e significa que você pode operá-lo apenas como uma string limitadora. sua portabilidade.

    
por 13.07.2015 / 02:36