7

Прошу прощения за новый вопрос, но этот вопрос меня совершенно сбил с толку.

У меня есть папка "Depositor", куда приходят пользовательские файлы, и я не могу контролировать имена входящих файлов.

Я создал парсер в PS, который довольно успешно перемещает файлы (на основе содержимого имени файла) в соответствующее место назначения.

Это прекрасно работает, кроме случаев, когда имя файла содержит либо «[» или «]».

Вот препроцессор "переименования", который фактически не может переименовать файл, содержащий один из символов надоедливых скобок:

 cd $folderpath
 foreach ($i in get-childitem $folderpath) {   
     if ($i.mode.substring(0,1) -ne “d”) {
        $name = $i.name.replace("[","_")
        $name = $name.replace("]","_")
        Write-Host $i -foregroundcolor “blue”       
        Write-Host $name -foregroundcolor “green”  

        Rename-Item $i $name 

     }
 }

Это также терпит неудачу для ren, copy, move и их эквивалентов командлетов

Любое понимание, которое вы могли бы предоставить, будет приветствоваться.

Заранее спасибо . , ,

3 ответа3

7

Если вы не используете -LiteralPath , квадратные скобки вызывают реальные проблемы с экранированием символов. Проблема заключается в том, что PowerShell несколько раз удаляет из строки строки и использует специальные символы для сопоставления с образцом. Получение PowerShell для правильного распознавания буквенной квадратной скобки в строке пути является сложным.

Если вы используете строки в одинарных кавычках, скобка требует двух обратных кавычек, чтобы избежать его. Если вы используете строки в двойных кавычках, скобка требует четырех обратных кавычек, чтобы избежать ее.

Если вы ищете файл с именем MyFile[1].txt , вам нужно использовать либо:

'MyFile``[1``].txt'

или же:

"MyFile````[1````].txt"

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

Допустим, вы хотите получить файл с буквальным названием [ab].txt .

Подстановочный шаблон, соответствующий шаблону Get-ChildItem , означает, что если он получает [ab].txt в качестве пути, он будет искать файлы с именами a.txt и b.txt . Итак, если мы хотим сопоставить литерал [ab].txt , мы должны выйти из скобок с помощью escape-символа: backtick. Это дает нам фактическую строку символов, которую мы хотим, чтобы Get-ChildItem использовал для спецификации файла:

`[ab`].txt

Тем не менее, мы должны передать эту спецификацию файла как строку. Это означает, что Get-ChildItem избежит этих недостатков, но это не то, что мы хотим! Мы хотим буквальные спины. Итак, мы избегаем обратных кавычек с обратными кавычками в нашей строке, чтобы убедиться, что Get-ChildItem использует правильную спецификацию файла:

'``[ab``].txt'

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

"````[ab````].txt"

Вот почему так много функций PowerShell, которые принимают спецификации файлов, имеют опцию -LiteralPath .

4

RenameItem не имеет -LiteralPath по какой-то глупой причине.*

Move-Item -LiteralPath $i -destination $name

* Извинения от со-дизайнера языка.

1

Это, наконец, достиг желаемого результата:

foreach ($i in get-childitem $folderpath) {
  if ($i.mode.substring(0,1) -ne “d”) {
    $name = $i.name.replace("[","_")
    $name = $name.replace("]","_")

   Write-Host $name -foregroundcolor “green”    
   [System.IO.File]::Move($folderPath+"\"+$i, $folderPath+"\"+$name) 
  }
}

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