rfilesystems

Check if two paths resolve to the same directory


In Check if two file paths resolve to the same file the solution is to use normalizePath; however, this appears to not be definitive for directories:

td1 <- tempdir()
td2 <- paste0(td1, "/")

dir.exists(td1) && dir.exists(td2)
#> [1] TRUE
file.create(file.path(td1, "foo.txt"))
#> [1] TRUE
file.exists(file.path(td2, "foo.txt"))
#> [1] TRUE

normalizePath(td1) == normalizePath(td2)
#> [1] FALSE

sessionInfo()
#> R version 3.5.1 (2018-07-02)
#> Platform: x86_64-w64-mingw32/x64 (64-bit)
#> Running under: Windows 10 x64 (build 17134)
#> 
#> Matrix products: default
#> 
#> locale:
#> [1] LC_COLLATE=English_Australia.1252  LC_CTYPE=English_Australia.1252   
#> [3] LC_MONETARY=English_Australia.1252 LC_NUMERIC=C                      
#> [5] LC_TIME=English_Australia.1252    
#> 
#> attached base packages:
#> [1] stats     graphics  grDevices utils     datasets  methods   base     
#> 
#> loaded via a namespace (and not attached):
#>  [1] compiler_3.5.1  backports_1.1.2 magrittr_1.5    rprojroot_1.3-2
#>  [5] tools_3.5.1     htmltools_0.3.6 yaml_2.2.0      Rcpp_0.12.18   
#>  [9] stringi_1.1.7   rmarkdown_1.10  knitr_1.20      stringr_1.3.1  
#> [13] digest_0.6.16   evaluate_0.11

Created on 2018-09-05 by the reprex package (v0.2.0).

Is there a method that is reliable (or more reliable) at identifying directories?


Solution

  • The accepted answer does not work for some very important directory cases, namely the "." case and "~" case. The normalizePath works for these. The accepted answer is also now inaccurate for more recent R. normalizePath is the only one that works in all cases.

    library(fs)
    
    # Case 1
    td1 <- tempdir()
    td2 <- paste0(td1, "/")
    dir.exists(td1) && dir.exists(td2)
    #> [1] TRUE
    file.create(file.path(td1, "foo.txt"))
    #> [1] TRUE
    file.exists(file.path(td2, "foo.txt"))
    #> [1] TRUE
    normalizePath(td1) == normalizePath(td2)
    #> [1] TRUE
    path_norm(td1) == path_norm(td2)
    #> [1] TRUE
    
    # Case 2
    td1 <- "."
    td2 <- getwd()
    dir.exists(td1) && dir.exists(td2)
    #> [1] TRUE
    file.create(file.path(td1, "foo.txt"))
    #> [1] TRUE
    file.exists(file.path(td2, "foo.txt"))
    #> [1] TRUE
    normalizePath(td1) == normalizePath(td2)
    #> [1] TRUE
    path_norm(td1) == path_norm(td2)
    #> [1] FALSE
    
    # Case 3
    td1 <- "~"
    td2 <- path.expand("~")
    dir.exists(td1) && dir.exists(td2)
    #> [1] TRUE
    file.create(file.path(td1, "foo.txt"))
    #> [1] TRUE
    file.exists(file.path(td2, "foo.txt"))
    #> [1] TRUE
    normalizePath(td1) == normalizePath(td2)
    #> [1] TRUE
    path_norm(td1) == path_norm(td2)
    #> [1] FALSE
    
    > sessionInfo()
    R version 4.4.0 (2024-04-24 ucrt)
    Platform: x86_64-w64-mingw32/x64
    Running under: Windows 10 x64 (build 19045)
    
    Matrix products: default
    
    
    locale:
    [1] LC_COLLATE=English_Canada.utf8  LC_CTYPE=English_Canada.utf8    LC_MONETARY=English_Canada.utf8
    [4] LC_NUMERIC=C                    LC_TIME=English_Canada.utf8    
    
    time zone: America/Vancouver
    tzcode source: internal
    
    attached base packages:
    [1] stats     graphics  grDevices utils     datasets  methods   base     
    
    other attached packages:
    [1] reprex_2.1.0
    
    loaded via a namespace (and not attached):
     [1] vctrs_0.6.5       cli_3.6.2         knitr_1.47        rlang_1.1.3       xfun_0.44         processx_3.8.4   
     [7] purrr_1.0.2       styler_1.10.3     glue_1.7.0        clipr_0.8.0       htmltools_0.5.8.1 ps_1.7.6         
    [13] fansi_1.0.6       rmarkdown_2.27    R.cache_0.16.0    evaluate_0.23     tibble_3.2.1      fastmap_1.2.0    
    [19] yaml_2.3.8        lifecycle_1.0.4   compiler_4.4.0    fs_1.6.4          pkgconfig_2.0.3   rstudioapi_0.16.0
    [25] R.oo_1.26.0       R.utils_2.12.3    digest_0.6.35     R6_2.5.1          utf8_1.2.4        pillar_1.9.0     
    [31] callr_3.7.6       magrittr_2.0.3    R.methodsS3_1.8.2 tools_4.4.0       withr_3.0.0  
    

    Created on 2024-06-03 with reprex v2.1.0