Не удается найти путь _, так как он не существует

Я пытаюсь создать небольшой скрипт в powershell, который будет перемещать файлы и каталоги для правильной локализации. Я сделал следующую команду:

      Get-ChildItem -Path '.\list\' | ForEach-Object { if ($($_.Name) -like '*[1]*') {
$file = $($_.Name)
$path = $($_.FullName)
echo "$file  ==>  $path"
Move-Item -Path $path -Destination .\[1]\}}

и он обнаруживает правильные файлы и каталоги, но не перемещает их.
Затем я решил немного изменить команду и вместо этого создать жесткие ссылки:

      Get-ChildItem -Path '.\list\' | ForEach-Object { if ($($_.Name) -like '*[1]*') {
$file = $($_.Name)
$path = $($_.FullName)
echo "$file  ==>  $path"
New-Item -Path ".\``[1``]\" -Name $file -Type HardLink -Target "$path"}}

и я получил следующий ответ (только 1 петля):

      [1] dir1  ==>  D:\test_move\list\[1] dir1
New-Item:
Line |
   5 |  New-Item -Path ".\``[1``]\" -Name $file -Type HardLink -Target "$path …
     |  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | Cannot find path 'D:\test_move\list\[1] dir1' because it does not exist.

Одна и та же ошибка появляется как с правами администратора, так и без них.

Что мне нужно сделать, чтобы заставить его работать?

1 ответ

Попробуйте следующее:

      Get-ChildItem -LiteralPath .\list -File -Filter '*[1]*' | ForEach-Object { 
  $file = $_.Name
  $path = $_.FullName
  "$file  ==>  $path" # implicit `echo` aka `Write-Output`
  New-Item -Force -Type HardLink `
           -Path (Join-Path .\[1] $file) `
           -Target ([WildcardPattern]::Escape($path)) ` # !! see PowerShell Core comments below
           -WhatIf
}

Примечание. Общий параметр в приведенной выше команде служит для предварительного просмотра операции. Удалять -WhatIfкак только вы убедитесь, что операция будет делать то, что вы хотите.

  • -Filter '*[1]*'предварительно фильтруетGet-ChildItemвывод включать только файлы, имя которых содержит подстроку дословно , потому что -FilterПараметр использует родной для файловой системы язык подстановочных знаков, который не обрабатывает и как метасимволы.

  • -Fileограничивает соответствие элементов файлам , потому что жесткие ссылки поддерживаются только для файлов, а не для каталогов.

  • -Path (Join-Path .\[1] $file)использовать только аргумент, а не аргумент только пути к каталогу в сочетании с аргументом только имени файла, что гарантирует, что аргумент обрабатывается как буквальный (дословный) путь без интерпретации метасимволов подстановки, таких как и .

    • К сожалению, в сочетании с -Nameприводит к тому, что аргумент интерпретируется как шаблон с подстановочными знаками .
  • создает целевой каталог по запросу, если это необходимо, но обратите внимание, что он также заменит любой ранее существовавший целевой файл.

  • Только Windows PowerShell : ([WildcardPattern]::Escape($path))экранирует целевой путь, чтобы обработать его дословно , когда он интерпретируется как подстановочный знак , который, к сожалению, интерпретируется как аргумент. Невыполнение этого экранирования вызвало ошибку, которую вы видели.

    • Предостережение :

      • В PowerShell [Core] 7+ в предложении GitHub № 13136было одобрено критическое изменение , чтобы — более разумно — рассматривать аргумент как буквальный (дословный) путь, и в этом случае вы просто использовали бы-Target $path.

      • Однако в PowerShell 7.1 это изменение еще не реализовано и, к сожалению, нацелено на путь, содержащий [а также ]в настоящее время полностью сломан — см. GitHub issue #14534.

Обратите внимание, что многие, но не все командлеты для обработки файлов предлагают -LiteralPathпараметр для явной передачи путей, которые должны быть восприняты буквально (дословно), в то время как -Pathпараметр — обычно подразумеваемый параметр для первого позиционного аргумента — предназначен для приема шаблонов подстановочных знаков.

Таким образом, вы могли бы сделать свой оригинальный подход сработайте следующим образом:

      # Ensure that the target dir. exists.
# No escaping needed for -Path when not combined with -Name.
$null = New-Item -Type Directory -Path .\[1] -Force 

# Move the file, targeted with -LiteralPath, there.
# No escaping needed for -Destination.
Move-Item -LiteralPath $path -Destination .\[1]\

Примечание. В отличие от , -Forceне создает целевой каталог по запросу. С другой стороны, Move-Itemх -Destinationболее разумно интерпретирует свой аргумент буквально (дословно), в отличие от New-Itemх -Targetпараметр.

Другие вопросы по тегам