У меня есть строка, которую я передаю в свой сценарий в качестве аргумента. Однако с целью отображения кода здесь я указал их вручную в коде.
Эти переменные:

  • $SearchFolder
  • $FileType

Код таким образом:

$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

Как видно, в конце последней строки я использую findstr -v -x $SearchFolder для отображения всех результатов, которые не соответствуют корневому каталогу (поиска), в данном случае C:\Users\Name\Downloads .

Выход, однако, таким образом:

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          

Эта проблема:
Как видно из вывода кода, хотя $SearchFolder и последняя строка вывода кажутся одинаковыми, очевидно, что они не совпадают, потому что в противном случае он не отображался бы. Я думаю, что там может быть мошеннический нулевой терминатор или конец строки, но поскольку я не знаю способа отладки с помощью PowerShell, я не могу быть уверен.

Что я хотел бы знать:
Как я мог бы по существу отфильтровать основной каталог, с помощью метода, используемого в настоящее время (или с помощью лучшего метода, если таковой существует).

1 ответ1

1

Похоже, вы либо приходите в PowerShell с сильным фоном CMD/Batch, либо пытаетесь адаптировать инструкции / учебники CMD/Batch.

Некоторые из проблем, с которыми вы можете столкнуться, это то, что вы пытаетесь использовать некоторые команды, как будто они запускаются из командной строки, а не из PowerShell. Я имею в виду, что в PowerShell dir не запускает команду dir, а скорее псевдоним для командлета PowerShell Get-ChildItem

Вот почему использование /s не будет работать, а командлеты PowerShell не принимают флаги '/', а скорее параметры '-'

Поскольку команда PowerShell знала, что люди будут использовать dir с ключом /s, они добавили s в качестве псевдонима для параметра -Recurse , поэтому эта часть команды работает.

Извините, что продолжаю рассказывать об этом, но я подумал, что некоторые сведения могут иметь значение.


На саму проблему. PowerShell работает с объектами и передает свои объекты по конвейеру, пока, наконец, не выведет объекты на консоль.

Команда findstr пытается работать со строками (и я не уверен на 100%, будет ли она работать на входе из конвейера PowerShell, если вы сократили его до просто строк).

Я бы предложил не использовать команду, а вместо этого использовать Where-Object (или, проще, его псевдоним Where)

Первый инстинкт должен сделать это:

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

Но вы обнаружите, что на самом деле в свойстве Directory хранится больше данных, чем вы видите, когда они записываются на консоль.

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

Есть два варианта учета этих дополнительных данных, используя подстановочный знак:

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

или протестируйте другое свойство, представляющее собой строку вопросов:

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

Однако если вы используете подход DirectoryName, вам нужно будет поместить его перед оператором Select, поскольку это свойство будет недоступно, если вы уже ограничили объект только каталогом.


Это конечный результат:

...
$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 

Я сожалею, что ответ длился намного дольше, чем я предполагал, надеюсь, это имеет смысл. Я подумал дать некоторую предысторию, и как и почему все это пошло бы немного дальше, чем просто «Вот фрагмент кода, который будет работать для вас»

Кроме того, я чувствую себя обязанным упомянуть, что в PowerShell echo - это псевдоним Write-Host который считается плохой практикой. Очевидно, что это полезно для вашей отладочной информации, но когда дело доходит до возврата результатов, вы можете просто вызвать переменную.

Это говорит о том, что PowerShell - это объекты. Возврат объекта (особенно как части функции) означает, что вы можете продолжать работать с данными как с объектом, однако, если вы запустите их через Write-Host, они преобразуются в строку и означает, что вы можете работать только с этим как с ограничением строки его мобильность.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .