2017-01-20 1 views
2

Я хочу сгенерировать строку для пути к файлу внутри скрипта powershell. Я хочу, чтобы это работало как в windows, так и в mac.Powershell для правильного создания путей к файлам в windows и unix

На данный момент кода HARDCODED к окнам, как тракты ("\" -> окно, "/" -> Unix): $templatep="$CoreRoot\templates\$serviceName"

я изменил это: $templatep= Join-Path $CoreRoot "templates" $serviceName И это работает в макинтоше с Powershell 6.0. НО он не работает на моем Windows Server с Powershell 4. Я должен сделать что-то вроде этого:

$templatep= Join-Path $CoreRoot -ChildPath "templates" | Join-Path -ChildPath $serviceName

Любая идея, почему это просто работает в моем макинтош? Это новая функция в PowerShell 5 или 6? Мне не нравится, когда вам нужно проехать несколько дорожек. Есть лучший способ сделать это?

Спасибо!

+2

Через PowerShell 5.0, насколько мне известно, «Join-Path» может принимать только два пути. Связывание с другим соединением или использование метода .Net '[io.path] :: comb()' являются двумя обходными решениями, о которых я знаю. – BenH

ответ

3

Во-первых, обходной с использованием структуры .NET:

[IO.Path]::Combine('a', 'b', 'c') 

Это дает a/b/c на Unix и a\b\c на Windows, и удобно поддерживает любое количество компонентов пути.

Примечание:

  • Этот способ предназначен только для файловой системы путей, в то время как Join-Path предназначен для работы с путями любого провайдера PowerShell привода.

  • Убедитесь, что ни одна компонента, кроме первых начинается с \ (Windows) или / (Unix), потому что любой предшествующий компонент затем игнорируется; например, на окнах:
    [IO.Path]::Combine('\a', '\b', 'c') # -> '\b\c' - '\a' is ignored(!)
    Отметьте, что Join-Path делает не проявляет это поведение; см. this answer.

В качестве альтернативы секвенирование Join-Path вызовов с трубопровода вы можете просто использование (...) (подвыражение):

Join-Path a (Join-Path b c) # -> 'a\b\c' (on Windows) 

У меня никакого объяснения разница в поведении; отображаемая Join-Path -? Синтаксис такой же, как на платформе, так как из Windows PowerShell версииv5.1.14393.693 и PowerShell Ядроv6.0.0-alpha.14 (случайные параметры опущены):

Join-Path [-Path] <String[]> [-ChildPath] <String> ... 

На основе этого синтаксиса, вызов Join-Path a b cдолжен результат в синтаксической ошибке, что действительно происходит на Windows (A positional parameter cannot be found that accepts argument 'c'), но не на платформах Unix. [1]

Это говорит, это, конечно, было бы удобно, если Join-Path работал с произвольным числом компонентов пути, а также тот факт, что он уже работает в PowerShell Ключевых, возможно, указывает на предстоящих изменениях в Windows PowerShell слишком ,

Обратите внимание, что даже если [-Path] <String[]> является массивом параметра, его цель состоит в том, чтобы не принимать несколько компонентов пути ребенка от одного выходного пути, но разрешить присоединение несколько пара пути родитель-ребенок; например:

$ Join-Path a,b c # same as: Join-Path -Path a,b -ChildPath c 
a\c 
b\c 

Наконец, даже , хотя это, вероятно, не рекомендуется, вы часто можете уйти с жестким кодированием / в качестве разделителей пути на оба платформ, так как многие функции Windows API, а также поскольку собственные командлеты PowerShell принимают \ и /взаимозаменяемо.
Однако не все утилиты могут вести себя таким образом, так что безопаснее использовать подходящий для платформы разделитель.

Например, следующие прекрасно работает на Windows:

Get-Item c:/windows/system32 # same as: Get-Item c:\windows\system32 

[1] Строго говоря, это не о платформе, но издание PowerShell: Join-Path a b c работает в многоплатформенная версия PowerShell Core даже в Windows - в отличие от Windows-родного Windows PowerShell издание (с п.5.1). Тем не менее, PowerShell Core обычно используется только на платформах Unix.

+1

спасибо за ответ. Я пойду обходной путь [IO.Path] :: Combine –

Смежные вопросы