Прокручуйте файли в каталозі за допомогою PowerShell


243

Як я можу змінити наступний код, щоб переглянути всі .log файли в каталозі, а не лише один файл?

Мені потрібно проглянути всі файли та видалити всі рядки, які не містять "step4" або "step9". Наразі це створить новий файл, але я не впевнений, як for eachтут використовувати цикл (новачок).

Фактичні файли названі так: 2013 09 03 00_01_29.log . Я хотів би, щоб вихідні файли або перезаписали їх, або ім’я SAME було додано з "out".

$In = "C:\Users\gerhardl\Documents\My Received Files\Test_In.log"
$Out = "C:\Users\gerhardl\Documents\My Received Files\Test_Out.log"
$Files = "C:\Users\gerhardl\Documents\My Received Files\"

Get-Content $In | Where-Object {$_ -match 'step4' -or $_ -match 'step9'} | `
Set-Content $Out

Відповіді:


363

Спробуйте:

Get-ChildItem "C:\Users\gerhardl\Documents\My Received Files" -Filter *.log | 
Foreach-Object {
    $content = Get-Content $_.FullName

    #filter and save content to the original file
    $content | Where-Object {$_ -match 'step[49]'} | Set-Content $_.FullName

    #filter and save content to a new file 
    $content | Where-Object {$_ -match 'step[49]'} | Set-Content ($_.BaseName + '_out.log')
}

Дякую. Частина BaseName не працює (версія 1), але мені вдалося спочатку створити резервну копію повного файлу, а потім внести зміни до вихідного файлу.
користувач2725402

6
Для v1 ви можете вилучити базове ім'я: [io.path] :: GetFileNameWithoutExtension ($ name)
Shay Levy

Якщо я заміню BaseNameз FullNameя отримую то , що хочу.
М--

78

Щоб отримати вміст каталогу, який ви можете використовувати

$files = Get-ChildItem "C:\Users\gerhardl\Documents\My Received Files\"

Тоді ви також можете перейти через цю змінну:

for ($i=0; $i -lt $files.Count; $i++) {
    $outfile = $files[$i].FullName + "out" 
    Get-Content $files[$i].FullName | Where-Object { ($_ -match 'step4' -or $_ -match 'step9') } | Set-Content $outfile
}

Ще простішим способом ввести це foreachцикл (завдяки @Soapy та @MarkSchultheiss):

foreach ($f in $files){
    $outfile = $f.FullName + "out" 
    Get-Content $f.FullName | Where-Object { ($_ -match 'step4' -or $_ -match 'step9') } | Set-Content $outfile
}

Це створює один вихідний файл під назвою "out.log". Як я можу створити окремий вихідний файл для кожного вхідного файлу?
користувач2725402

@ user2725402 Я додав вхідний залежний вивідний файл, який названий <ім'я вхідного файлу> вихід
PVitt

не впевнений, що я роблю неправильно, але це не працює - тепер я не отримую вихідних файлів (і жодних помилок): $files = Get-ChildItem "C:\Users\gerhardl\Documents\My Received Files\" $files | Where-Object { $outFile = $_.Name + "out" Get-Content $_.FullName | Where-Object { $_ -match 'step4' -or $_ -match 'step9' } | Set-Content $outFile }
user2725402

2
Ви також можете зробитиforeach ($f in Get-ChildItem "C:\Users\gerhardl\Documents\My Received Files\") { ... }
Soapy

1
або використовуватиForEach ($f in $files){...}
Марк Шультейс

31

Якщо вам потрібно рециркулювати цикл всередині каталогу для певного типу файлів, скористайтеся командою нижче, яка фільтрує всі файли типу docфайлу

$fileNames = Get-ChildItem -Path $scriptPath -Recurse -Include *.doc

Якщо вам потрібно виконати фільтрацію для декількох типів, скористайтеся командою нижче.

$fileNames = Get-ChildItem -Path $scriptPath -Recurse -Include *.doc,*.pdf

Тепер $fileNamesзмінна діє як масив, з якого можна циклічно застосовувати свою логіку бізнесу.


Мене непокоїло - це упущення прихованих та / або системних файлів. Щоб також їх побачити, ви повинні використовувати -Forceпараметр Get-ChildItem. Дивіться його документа на docs.microsoft.com/en-us/powershell/module/… .
til_b

-6

Інші відповіді чудові, я просто хочу додати ... інший підхід, застосований у PowerShell: Встановіть утиліти GNUWin32 та використовуйте grep для перегляду рядків / перенаправлення виводу на файл http://gnuwin32.sourceforge.net/

Це кожного разу перезаписує новий файл:

grep "step[49]" logIn.log > logOut.log 

До цього додається вихід журналу, якщо ви перезаписали файл входу та хочете зберегти дані:

grep "step[49]" logIn.log >> logOut.log 

Примітка: щоб мати змогу використовувати утиліти GNUWin32 у всьому світі, вам слід додати папку бін до системного шляху.


18
Це питання було позначено як PowerShell, а не Unix
SteveC

2
Так. Очевидно. Моє прийняття було досить простим: Ви можете використовувати утиліти GNUWin32 в Windows, тому ви можете легко використовувати інструменти * nix в Powershell. Працює. Ніхто ніколи не говорив, що відповідь повинна бути повністю рідною для Пауершелла. І навіть якщо вони це зробили, ви все одно можете зателефонувати Win32 Utils безпосередньо з Powershell. AFAIK, використовуючи все, що доступно та сумісно, ​​насправді не є поганою справою.
користувач1628658

2
Я би відредагував свій попередній коментар, але я пройшов 5-хвилинний ліміт: SteveC: Ви хочете сказати, що включення інструментів GNU, які добре працюють під Windows, якимось чином не піддається Powershell? Це одне. Я розумію, що опрацювання цього досвіду виключно в Powershell може бути більш продуктивним за короткий термін. У довгостроковій перспективі розширення можливостей має насправді більше заслуг. Ви додаєте більше опцій і повністю працюєте в Windows і Powershell без будь-яких емуляторів Linux, таких як Cygwin. Тож, поки я розумію ваше бронювання, я не згоден.
користувач1628658

5
Питання полягало в тому, щоб шукати в PowerShell, а не про безліч інших мов, якими можна користуватися.
SteveC

1
Відповіді мають бути на запитання. Це запитання було явним, оскільки воно вимагало відповіді в PowerShell. Вашою відповіддю було щось встановити і використовувати. Ви могли запропонувати встановити Ruby тощо.
SteveC
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.