dirs.nim 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. ## This module implements directory handling.
  2. from std/paths import Path, ReadDirEffect, WriteDirEffect
  3. from std/private/osdirs import dirExists, createDir, existsOrCreateDir, removeDir,
  4. moveDir, walkDir, setCurrentDir,
  5. walkDirRec, PathComponent
  6. export PathComponent
  7. proc dirExists*(dir: Path): bool {.inline, tags: [ReadDirEffect], sideEffect.} =
  8. ## Returns true if the directory `dir` exists. If `dir` is a file, false
  9. ## is returned. Follows symlinks.
  10. result = dirExists(dir.string)
  11. proc createDir*(dir: Path) {.inline, tags: [WriteDirEffect, ReadDirEffect].} =
  12. ## Creates the `directory`:idx: `dir`.
  13. ##
  14. ## The directory may contain several subdirectories that do not exist yet.
  15. ## The full path is created. If this fails, `OSError` is raised.
  16. ##
  17. ## It does **not** fail if the directory already exists because for
  18. ## most usages this does not indicate an error.
  19. ##
  20. ## See also:
  21. ## * `removeDir proc`_
  22. ## * `existsOrCreateDir proc`_
  23. ## * `moveDir proc`_
  24. createDir(dir.string)
  25. proc existsOrCreateDir*(dir: Path): bool {.inline, tags: [WriteDirEffect, ReadDirEffect].} =
  26. ## Checks if a `directory`:idx: `dir` exists, and creates it otherwise.
  27. ##
  28. ## Does not create parent directories (raises `OSError` if parent directories do not exist).
  29. ## Returns `true` if the directory already exists, and `false` otherwise.
  30. ##
  31. ## See also:
  32. ## * `removeDir proc`_
  33. ## * `createDir proc`_
  34. ## * `moveDir proc`_
  35. result = existsOrCreateDir(dir.string)
  36. proc removeDir*(dir: Path, checkDir = false
  37. ) {.inline, tags: [WriteDirEffect, ReadDirEffect].} =
  38. ## Removes the directory `dir` including all subdirectories and files
  39. ## in `dir` (recursively).
  40. ##
  41. ## If this fails, `OSError` is raised. This does not fail if the directory never
  42. ## existed in the first place, unless `checkDir` = true.
  43. ##
  44. ## See also:
  45. ## * `removeFile proc <files.html#removeFile>`_
  46. ## * `existsOrCreateDir proc`_
  47. ## * `createDir proc`_
  48. ## * `moveDir proc`_
  49. removeDir(dir.string, checkDir)
  50. proc moveDir*(source, dest: Path) {.inline, tags: [ReadIOEffect, WriteIOEffect].} =
  51. ## Moves a directory from `source` to `dest`.
  52. ##
  53. ## Symlinks are not followed: if `source` contains symlinks, they themself are
  54. ## moved, not their target.
  55. ##
  56. ## If this fails, `OSError` is raised.
  57. ##
  58. ## See also:
  59. ## * `moveFile proc <files.html#moveFile>`_
  60. ## * `removeDir proc`_
  61. ## * `existsOrCreateDir proc`_
  62. ## * `createDir proc`_
  63. moveDir(source.string, dest.string)
  64. iterator walkDir*(dir: Path; relative = false, checkDir = false,
  65. skipSpecial = false):
  66. tuple[kind: PathComponent, path: Path] {.tags: [ReadDirEffect].} =
  67. ## Walks over the directory `dir` and yields for each directory or file in
  68. ## `dir`. The component type and full path for each item are returned.
  69. ##
  70. ## Walking is not recursive.
  71. ## * If `relative` is true (default: false)
  72. ## the resulting path is shortened to be relative to ``dir``,
  73. ## otherwise the full path is returned.
  74. ## * If `checkDir` is true, `OSError` is raised when `dir`
  75. ## doesn't exist.
  76. ## * If `skipSpecial` is true, then (besides all directories) only *regular*
  77. ## files (**without** special "file" objects like FIFOs, device files,
  78. ## etc) will be yielded on Unix.
  79. for (k, p) in walkDir(dir.string, relative, checkDir, skipSpecial):
  80. yield (k, Path(p))
  81. iterator walkDirRec*(dir: Path,
  82. yieldFilter = {pcFile}, followFilter = {pcDir},
  83. relative = false, checkDir = false, skipSpecial = false):
  84. Path {.tags: [ReadDirEffect].} =
  85. ## Recursively walks over the directory `dir` and yields for each file
  86. ## or directory in `dir`.
  87. ##
  88. ## Options `relative`, `checkdir`, `skipSpecial` are explained in
  89. ## [walkDir iterator] description.
  90. ##
  91. ## .. warning:: Modifying the directory structure while the iterator
  92. ## is traversing may result in undefined behavior!
  93. ##
  94. ## Walking is recursive. `followFilter` controls the behaviour of the iterator:
  95. ##
  96. ## ===================== =============================================
  97. ## yieldFilter meaning
  98. ## ===================== =============================================
  99. ## ``pcFile`` yield real files (default)
  100. ## ``pcLinkToFile`` yield symbolic links to files
  101. ## ``pcDir`` yield real directories
  102. ## ``pcLinkToDir`` yield symbolic links to directories
  103. ## ===================== =============================================
  104. ##
  105. ## ===================== =============================================
  106. ## followFilter meaning
  107. ## ===================== =============================================
  108. ## ``pcDir`` follow real directories (default)
  109. ## ``pcLinkToDir`` follow symbolic links to directories
  110. ## ===================== =============================================
  111. ##
  112. ##
  113. ## See also:
  114. ## * `walkDir iterator`_
  115. for p in walkDirRec(dir.string, yieldFilter, followFilter, relative,
  116. checkDir, skipSpecial):
  117. yield Path(p)
  118. proc setCurrentDir*(newDir: Path) {.inline, tags: [].} =
  119. ## Sets the `current working directory`:idx:; `OSError`
  120. ## is raised if `newDir` cannot been set.
  121. ##
  122. ## See also:
  123. ## * `getCurrentDir proc <paths.html#getCurrentDir>`_
  124. osdirs.setCurrentDir(newDir.string)