@ Joe, estúpido está certo! Além disso, devo salientar que a função equivalente funciona muito bem no Node.JS ... Balançando a cabeça na Microsoft ...
NH.
2
@zwcloud Para o .NET Core / Standard, Path.Combine()é principalmente para compatibilidade com versões anteriores (com o comportamento existente). Você seria melhor usar Path.Join(): "Diferentemente do método Combine, o método Join não tenta fazer root no caminho retornado. (Ou seja, se path2 é um caminho absoluto, o método Join não descarta o caminho1 e retorna o caminho2 como o Combine método faz.) "
Stajs 17/09/19
Respostas:
205
Essa é uma pergunta filosófica (que talvez apenas a Microsoft possa responder de verdade), pois está fazendo exatamente o que a documentação diz.
Não sei qual é a lógica. Eu acho que a solução é remover (ou aparar) o DirectorySeparatorChar do início do segundo caminho; talvez escreva seu próprio método Combine que faça isso e depois chame Path.Combine ().
Olhando para o código desmontado (veja meu post), você está certo de uma maneira.
Gulzar Nazim
7
Eu acho que funciona dessa maneira para permitir acesso fácil ao algoritmo "diretório de trabalho atual".
BCS
Parece funcionar como fazer uma sequência a cd (component)partir da linha de comando. Parece razoável para mim.
Adrian Ratnapala
11
Eu uso esse trim para obter o efeito desejado string strFilePath = Path.Combine (basePath, otherPath.TrimStart (new char [] {'\\', '/'}));
Matthew Lock,
3
Eu mudava o meu código de trabalho em Path.Combineapenas para ser seguro, mas, em seguida, ele quebrou .. É tão estúpido :)
SOTN
23
Este é o código desmontado do .NET Reflector para o método Path.Combine. Verifique a função IsPathRooted. Se o segundo caminho estiver enraizado (começa com um DirectorySeparatorChar), retorne o segundo caminho como está.
Eu também acho que é bastante irritante que esse tratamento de string tenha que ser feito manualmente, e eu estaria interessado na razão por trás disso.
Na minha opinião, isso é um bug. O problema é que existem dois tipos diferentes de caminhos "absolutos". O caminho "d: \ mydir \ myfile.txt" é absoluto, o caminho "\ mydir \ myfile.txt" também é considerado "absoluto", mesmo faltando a letra da unidade. O comportamento correto, na minha opinião, seria preceder a letra da unidade do primeiro caminho quando o segundo caminho iniciar com o separador de diretório (e não é um caminho UNC). Eu recomendaria escrever sua própria função de wrapper auxiliar, com o comportamento desejado, se você precisar.
Ele corresponde às especificações, mas também não é o que eu esperava.
dthrasher 26/09/09
@ Jake Isso não está evitando uma correção de bug; são várias pessoas que pensam muito sobre como fazer algo e depois se apegam ao que concordam. Além disso, observe a diferença entre a estrutura .Net (uma biblioteca que contém Path.Combine) e a linguagem C #.
Se um dos caminhos especificados for uma cadeia de comprimento zero, esse método retornará o outro caminho. Se path2 contiver um caminho absoluto, esse método retornará path2.
Isso significa que, quando você une um caminho com uma barra anterior, na verdade você está unindo uma base à outra; nesse caso, a segunda obtém precedência.
Isso realmente faz sentido, de alguma forma, considerando como os caminhos (relativos) são tratados normalmente:
stringGetFullPath(string path){string baseDir =@"C:\Users\Foo.Bar";returnPath.Combine(baseDir, path);}// Get full path for RELATIVE file pathGetFullPath("file.txt");// = C:\Users\Foo.Bar\file.txt// Get full path for ROOTED file pathGetFullPath(@"C:\Temp\file.txt");// = C:\Temp\file.txt
A verdadeira questão é: Por que os caminhos, que começam com "\", são considerados "enraizados"? Isso também era novo para mim, mas funciona assim no Windows :
Isso \ significa "o diretório raiz da unidade atual". No seu exemplo, significa a pasta "test" no diretório raiz da unidade atual. Portanto, isso pode ser igual a "c: \ test".
Como mencionado por Ryan, está fazendo exatamente o que a documentação diz.
Desde os tempos do DOS, o disco atual e o caminho atual são diferenciados.
\é o caminho raiz, mas para o DISCO ATUAL.
Para cada " disco ", há um " caminho atual " separado . Se você alterar o disco usando cd D:, não altere o caminho atual para D:\, mas para: "D: \ qualquer \ foi \ o \ último \ caminho \ acessado \ neste \ disco" ...
Portanto, no Windows, um literal @"\x"significa: "CURRENTDISK: \ x". Portanto, Path.Combine(@"C:\x", @"\y")tem como segundo parâmetro um caminho raiz, não um parente, embora não em um disco conhecido ... E como não se sabe qual pode ser o «disco atual», o python retorna "\\y".
Path.Combine()
é principalmente para compatibilidade com versões anteriores (com o comportamento existente). Você seria melhor usarPath.Join()
: "Diferentemente do método Combine, o método Join não tenta fazer root no caminho retornado. (Ou seja, se path2 é um caminho absoluto, o método Join não descarta o caminho1 e retorna o caminho2 como o Combine método faz.) "Respostas:
Essa é uma pergunta filosófica (que talvez apenas a Microsoft possa responder de verdade), pois está fazendo exatamente o que a documentação diz.
System.IO.Path.Combine
"Se path2 contiver um caminho absoluto, este método retornará path2."
Aqui está o método Combine real da fonte .NET. Você pode ver que ele chama CombineNoChecks , que chama IsPathRooted no caminho2 e retorna esse caminho, se assim for:
Não sei qual é a lógica. Eu acho que a solução é remover (ou aparar) o DirectorySeparatorChar do início do segundo caminho; talvez escreva seu próprio método Combine que faça isso e depois chame Path.Combine ().
fonte
cd (component)
partir da linha de comando. Parece razoável para mim.Path.Combine
apenas para ser seguro, mas, em seguida, ele quebrou .. É tão estúpido :)Este é o código desmontado do .NET Reflector para o método Path.Combine. Verifique a função IsPathRooted. Se o segundo caminho estiver enraizado (começa com um DirectorySeparatorChar), retorne o segundo caminho como está.
fonte
Eu queria resolver este problema:
Obviamente, todos os caminhos de 1 a 9 devem conter uma sequência equivalente no final. Aqui está o método PathCombine que eu criei:
Eu também acho que é bastante irritante que esse tratamento de string tenha que ser feito manualmente, e eu estaria interessado na razão por trás disso.
fonte
Na minha opinião, isso é um bug. O problema é que existem dois tipos diferentes de caminhos "absolutos". O caminho "d: \ mydir \ myfile.txt" é absoluto, o caminho "\ mydir \ myfile.txt" também é considerado "absoluto", mesmo faltando a letra da unidade. O comportamento correto, na minha opinião, seria preceder a letra da unidade do primeiro caminho quando o segundo caminho iniciar com o separador de diretório (e não é um caminho UNC). Eu recomendaria escrever sua própria função de wrapper auxiliar, com o comportamento desejado, se você precisar.
fonte
Path.Combine
) e a linguagem C #.Do MSDN :
No seu exemplo, path2 é absoluto.
fonte
Seguindo o conselho de Christian Graus no blog "Coisas que odeio sobre a Microsoft", intitulado " Path.Combine é essencialmente inútil. ", Eis a minha solução:
Alguns aconselham que os namespaces colidam, ... eu fui
Pathy
, como um pouco, e para evitar colisões com namespacesSystem.IO.Path
.Editar : Adicionadas verificações de parâmetro nulo
fonte
Este código deve fazer o truque:
fonte
Sem saber os detalhes reais, meu palpite é que ele tenta entrar como se você fosse um URI relativo. Por exemplo:
Isso significa que, quando você une um caminho com uma barra anterior, na verdade você está unindo uma base à outra; nesse caso, a segunda obtém precedência.
fonte
Razão:
Seu segundo URL é considerado um caminho absoluto. O
Combine
método retornará o último caminho apenas se o último caminho for um caminho absoluto.Solução: basta remover a barra inicial
/
do seu segundo caminho (/SecondPath
paraSecondPath
). Então funciona como você excluiu.fonte
Isso realmente faz sentido, de alguma forma, considerando como os caminhos (relativos) são tratados normalmente:
A verdadeira questão é: Por que os caminhos, que começam com
"\"
, são considerados "enraizados"? Isso também era novo para mim, mas funciona assim no Windows :fonte
Se você deseja combinar os dois caminhos sem perder nenhum caminho, pode usar isto:
Ou com variáveis:
Ambos os casos retornam "C: \ test \ test".
Primeiro, avalio se o Path2 começa com / e, se for verdadeiro, retorne o Path2 sem o primeiro caractere. Caso contrário, retorne o Path2 completo.
fonte
== @"\"
cheque por umaPath.IsRooted()
chamada, pois esse"\"
não é o único caractere a ser considerado.Esses dois métodos devem evitar que você junte acidentalmente duas seqüências que possuem o delimitador.
fonte
Isso \ significa "o diretório raiz da unidade atual". No seu exemplo, significa a pasta "test" no diretório raiz da unidade atual. Portanto, isso pode ser igual a "c: \ test".
fonte
Remova a barra inicial ('\') no segundo parâmetro (caminho2) do Path.Combine.
fonte
Eu usei a função agregada para forçar caminhos combinados como abaixo:
fonte
Como mencionado por Ryan, está fazendo exatamente o que a documentação diz.
Desde os tempos do DOS, o disco atual e o caminho atual são diferenciados.
\
é o caminho raiz, mas para o DISCO ATUAL.Para cada " disco ", há um " caminho atual " separado . Se você alterar o disco usando
cd D:
, não altere o caminho atual paraD:\
, mas para: "D: \ qualquer \ foi \ o \ último \ caminho \ acessado \ neste \ disco" ...Portanto, no Windows, um literal
@"\x"
significa: "CURRENTDISK: \ x". Portanto,Path.Combine(@"C:\x", @"\y")
tem como segundo parâmetro um caminho raiz, não um parente, embora não em um disco conhecido ... E como não se sabe qual pode ser o «disco atual», o python retorna"\\y"
.fonte