Непонятные штуки — $_ и % в Power Shell
Очень часто нам приходится совершать некую операцию над группой объектов — файлов, процессов, текстовых строк, и т.д. Делать это в PowerShell можно разными способами. Например For:
1
2
3
4
5
6
7
8
9
10
11
12
|
# Получаем объекты представляющие файлы в переменную $files
$Files = dir C:\root\test
# С помощью for:
# 1) объявляем переменную $i, и присваиваем ей значение 0
# 2) указываем условие повторения цикла($i меньше количества файлов)
# 3) указываем что после каждого выполнения цикла надо увеличить $i на единицу
for ($i=0; $i -lt $files.Count; $i++)
{
# Пока условие удовлетворяется, вызываем утилиту md5.exe, передавая ей в
# качестве аргумента элемент массива файлов под номером $i (отсчет идет с 0)
md5.exe $files[$i]
}
|
И вот результат:

For очень популярен, присутствует во множестве языков, но тем не менее обладает некоторыми недостатками. Во первых это необходимость использования временной переменной для перебора, во вторых — излишняя сложность конструкции. Гораздо проще для перебора группы объектов использовать ForEach:
1
2
3
4
5
6
7
8
|
# Получаем объекты представляющие файлы в переменную $files
$Files = dir C:\root\test
# Каждый объект из $Files по очереди помещается в переменную $File
ForEach ($File in $Files)
{
# ... и выполняется блок кода...
md5.exe $File
}
|
Или еще короче:

Способ отличный, но тоже не лишен недостатков. Обычно работая в консоли я сначала выполняю команду dir или get-*, для того чтобы посмотреть на список объектов, а затем уже хочу обработать их. Для использования ForEach мне пришлось бы возвращаться в начало строки, дописывать там Foreach ($obj in ( затем идет код получения объектов, затем закрывающие скобки и затем уже код для выполнения. Не слишком удобно для быстрой работы. Но к счастью есть командлет Foreach-Object. В него можно просто перенаправить полученные объекты, и указать блок кода для выполнения. При этом даже не нужно указывать имя для временного объекта — он всегда будет представлен под именем $_

Так как этот командлет предназначен в первую очередь для интерактивной работы, то у него есть два псевдонима: ForEach (хоть и почти идентичен ранее упомянутому ключевому слову, путать их не стоит) и % (знак процента). Вот это уже гораздо удобнее для работы в шелле, хоть и выглядит страшновато для непосвященных

Удобнее может быть только использование PowerShell’овских командлетов или скриптов умеющих обрабатывать объекты получаемые по конвейеру. Тут уже не надо никаких For и Foreach

На самом деле я изложил тут лишь одно применение переменной $_ (кстати она называется «Default variable»), хоть и наиболее популярное. $_ используется еще во многих местах, обычно представляя «текущий объект». Но думаю теперь вам будет проще понять и эти случаи. Например в командлете Where-Object $_ исполняет ту же роль что и в ForeEach-Object — содержит текущий объект конвейера. А в блоке обработки ошибок (trap), за $_ будет скрываться объект текущей ошибки.