В настоящее время, когда я просматриваю кучу файлов для строки в powershell, я использую следующее:

PS: C:\> ls -r | Select-String "dummy" | ls -r

И это перечисляет все файлы, которые имеют эту строку в них. Если я сделаю либо

PS: C:\> ls -r | Select-String "dummy" | ls -r | cat
PS: C:\> ls -r | Select-String "dummy" | cat

Он снова будет искать и отыскивать все файлы, которые содержат строку, но все это получается одним куском, как

file 1 line 1
file 1 line 2
file 2 line 1
file 3 line 1
file 4 line 1

Но невозможно определить, какая строка в каком файле. Есть ли способ, чтобы это было что-то вроде:

File 1.txt:
file1 line1
file2 line2

File 2.txt:
file2 line1

и т.д. Один лайнер будет предпочтительным, но не обязательно

1 ответ1

3

Можно утверждать, что это не однострочный текст, но он должен работать в любом случае ("должен" означает, что я его не проверял, но сценарий должен быть верным):

Get-ChildItem -Recurse | Where-Object {(Select-String -InputObject $_ -Pattern 'dummy' -Quiet) -eq $true} | ForEach-Object {Write-Output $_; Get-Content $_}

Расширено, с комментариями:

# Get a listing of all files within this folder and its subfolders.
Get-ChildItem -Recurse |

# Filter files according to a script.
Where-Object {
    # Pick only the files that contain the string 'dummy'.
    # Note: The -Quiet parameter tells Select-String to only return a Boolean. This is preferred if you just need to use Select-String as part of a filter, and don't need the output.
    (Select-String -InputObject $_ -Pattern 'dummy' -Quiet) -eq $true
} |

# Run commands against each object found.
ForEach-Object {
    # Output the file properties.
    Write-Output $_;

    # Output the file's contents.
    Get-Content $_
}

А вот "игра в гольф", если вы действительно хотите, чтобы она была короткой. Это определенно приближается к квалификации "однострочник".

ls -R|?{$_|Select-String 'dummy'}|%{$_;gc $_}

Помимо очевидного использования псевдонимов, сжатия пробелов и усечения имен параметров, вы можете отметить следующие существенные различия между "полными" версиями и "полными" версиями:

  • Select-String поменялся местами для использования конвейерного ввода вместо -InputObject .
  • Имя параметра -Pattern было опущено в Select-String , так как использование имени этого параметра необязательно.
  • Опция -Quiet была удалена из Select-String . Фильтр все еще будет работать, но это займет больше времени, так как Select-String будет обрабатывать каждый завершенный файл вместо остановки после первой соответствующей строки.
  • -eq $true было опущено в правиле фильтра. Когда скрипт фильтра уже возвращает логическое значение, вам не нужно добавлять оператор сравнения и объект, если вы просто хотите, чтобы он работал, когда логическое значение истинно.
    • (Также обратите внимание, что это будет работать для некоторых не-Booleans, как в этом сценарии. Здесь совпадение приведет к заполненному объекту массива, который рассматривается как истина, в то время как несоответствие вернет пустой массив, который рассматривается как ложь.)
  • Write-Output был опущен. PowerShell попытается сделать это как действие по умолчанию, если объект задан без команды.

Если вам не нужны все свойства файла, и вы хотите указать полный путь в одной строке перед содержимым файла, вы можете использовать это вместо этого:

ls -R|?{$_|Select-String 'dummy'}|%{$_.FullName;gc $_}

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