Указание фильтра * .xls в Get-ChildItem также возвращает результаты * .xlsx - PullRequest
1 голос
/ 11 февраля 2020

У меня есть папка, содержащая файлы .xls, .xlsx и .xlsm, и я хочу фильтровать только файлы .xls.

Почему следующая строка не работает так, как я ожидал? к? Я вижу результаты .xls, .xlsx и .xlsm.

Get-ChildItem $(Get-Location) -Filter *.xls | ForEach-Object { $_.Extension }

Ответы [ 2 ]

1 голос
/ 11 февраля 2020

Подстановочный знак параметра -Filter соответствует , а не , выполненному PowerShell , он передается поставщику файловой системы и в конечном итоге API Windows. Сопоставление, выполняемое там, обременено множеством унаследованных поведений и причуд, включая тот, который вы видели:

  • In Windows PowerShell , -Filter *.xls эффективно ведет себя как -Filter *.xls*. Следовательно, -Filter *.xls соответствует, например, foo.xls и foo.xlsx; это происходит потому, что 8,3 (короткие) имена файлов также сопоставляются за кадром ; например, имя файла foo.xlsx 8.3 выглядит примерно так: FOO~1.XLS; обратите внимание на усечение (и заглавные буквы) от .xlsx до .XLS.

  • В то время как поведение сопоставления коротких имен больше не происходит в PowerShell [Core] v6 + К счастью, сохраняются другие устаревшие особенности [1] , как и самое заметное отличие (которое не будет go прочь): только PowerShell подстановочные выражения (см. about_Wildcards) поддержка диапазонов / наборов символов с помощью [...] (например, [a-z]) - они не поддерживаются с -Filter .

  • Использование параметра -Filter в целом все еще предпочтительнее - -Path / -Include (см. Ниже) из-за его превосходящего качества. производительность (фильтрация в источнике , а не по факту в PowerShell).

Обходной путь заключается в использовании -Path параметр , чтобы использовать сопоставление с подстановочными знаками PowerShell:

Get-ChildItem -Path (Join-Path (Get-Location) *.xls) | ForEach-Object { $_.Extension }

# Or, more simply
Get-ChildItem -Path $PWD/*.xls | ForEach-Object Extension

Примечание: При -Recurse вместо параметра -Include будет использоваться .


[1] Известны другие причуды:

  • Несколько последовательных подстановочных знаков ? могут соответствовать именам с меньше символов.

    • Например, Get-ChildItem -Filter ??.txt соответствует aa.txt и неожиданно также a.txt
    • Примечание. Это было временно исправлено в PowerShell Core 6.x (по состоянию на 6.2.3), но поведение возвращается к PowerShell Core 7.0.0-r c .2
  • Шаблон *. соответствует файлу и каталогу без расширения имена.

    • Например, Get-ChildItem -File -Filter *. находит все файлы (-File), чьи имена не имеют расширения (например, file); эта причуда может быть полезна тем, что это самый простой и эффективный способ найти файлы без расширений (-Path *. не не работает, потому что он ищет имя файла буквально , оканчивающийся на .).

    • Примечание. Это было временно изменено в PowerShell Core 6.x (по состоянию на 6.2.3), но поведение возвращено к PowerShell Core 7.0.

  • И наоборот, *.* также включает имена файлов и каталогов без расширения.

См. этот превосходный ответ от Zenexer для предыстории и кровавых подробностей.

0 голосов
/ 11 февраля 2020

-filter соответствует короткой версии имени файла. Это было рассмотрено в другом месте. Это решено в PowerShell 6.

echo hi > file.xlsx
dir -filter *.xls


    Directory: C:\users\js\foo


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----        2/11/2020   9:54 AM              4 file.xlsx


cmd /c dir /x

 Volume in drive C is DISK
 Volume Serial Number is A11A-AA11

 Directory of C:\users\js\foo

02/11/2020  09:54 AM    <DIR>                       .
02/11/2020  09:54 AM    <DIR>                       ..
02/11/2020  09:54 AM                 4 FILE~1.XLS   file.xlsx
               1 File(s)              4 bytes
               2 Dir(s)   3,380,170,752 bytes free
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...