ObjectivePaths

ObjectivePaths is a small Julia library aiming to make a few operations around handling paths to folders and files easier. It's a small wrapper around Base's file system applying some ideas from Python's pathlib library, in a Julian way.

Installation:

] add ObjectivePaths

AbstractPath, Folder & File

The first thing you need is to craete pointers to paths (folders/files). This is done by calling the path function on a string with a filepath:

using ObjectivePaths

current_folder = pwd()  # path to current folder
path(current_folder)    # create a Folder type
๐Ÿ“ folder: / > home > runner > work > ObjectivePaths.jl > ObjectivePaths.jl     
> docs > build                                                                  
โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”
exists: โœ” | # files: 0                                                          

(note: the display in the REPR will look a bit different in your terminal - give it a go by copy-pasting the code above and running it in the REPL).

As you can see, calling path on a string pointing to a file create a Folder type. If, instead, you are using a file:

parent_content = readdir(parent(path(current_folder)); join=true) # get content of parent folder
files_paths = filter(isfile, parent_content)                     # get only files
path(files_paths[1])  # pointer to a file
๐Ÿ“„ file: / > home > runner > work > ObjectivePaths.jl > ObjectivePaths.jl       
> docs > Manifest.toml                                                          
โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”
exists: โœ” | # size: 11.3 KB                                                     

this creates a File. These are the two subtypes of AbstractPath. There's a few methods for AbstractPaths which can make your life easier, starting from printing nicely formatted info as shown above. But you can do more

fld = path(current_folder)  # Folder object
println(fld)

exists(fld) |> println  # true if folder exists
nfiles(fld) |> println  # number of files in folder
name(fld) |> println    # name of folder (last part of the path)

# also mose Base methods are available for AbstractPaths
split(fld) |> println   # split path into base/name
๐Ÿ“ folder: / > home > runner > work > ObjectivePaths.jl > ObjectivePaths.jl     
> docs > build                                                                  
โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”
exists: โœ” | # files: 0

true
0
build
(Folder("/home/runner/work/ObjectivePaths.jl/ObjectivePaths.jl/docs"), "build")

Folder-specific methods

With Folder objects you can do a few more, starting from viewing more info (or use tree to just print out the folder structure):

info(fld - 1)  # -1 moves us one level up the hierarchy
โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
โ”‚                                                                              โ”‚
โ”‚                 ๐Ÿ“ folder:/ > home > runner > work > ObjectivePaths.jl       โ”‚
โ”‚     > ObjectivePaths.jl                                                      โ”‚
โ”‚                 > docs                                                       โ”‚
โ”‚                                                                              โ”‚
โ”‚                 โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”      โ”‚
โ”‚     โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”                                                โ”‚
โ”‚                                                                              โ”‚
โ”‚                                                                              โ”‚
โ”‚                                                                              โ”‚
โ”‚                 โ”Œโ”€โ”€โ”€โ”€ properties โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                               โ”‚
โ”‚     docs                                                                     โ”‚
โ”‚                 โ”‚                            โ”‚                               โ”‚
โ”‚       โ”œโ”€ files โ‡’ Any[nothing => "Manifest.toml", nothing                     โ”‚
โ”‚                 โ”‚                 value      โ”‚                               โ”‚
โ”‚       โ”‚          => "Project.toml", nothing => "make.jl"]                    โ”‚
โ”‚                 โ”‚   โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€    โ”‚                               โ”‚
โ”‚       โ”‚          โ”œโ”€ 1 โ‡’ nothing => "Manifest.toml"                           โ”‚
โ”‚                 โ”‚       exists     yes       โ”‚                               โ”‚
โ”‚       โ”‚          โ”‚      โ””โ”€ 1 โ‡’ Manifest.toml                                 โ”‚
โ”‚                 โ”‚                            โ”‚                               โ”‚
โ”‚       โ”‚          โ”œโ”€ 2 โ‡’ nothing => "Project.toml"                            โ”‚
โ”‚                 โ”‚      # files      5        โ”‚                               โ”‚
โ”‚       โ”‚          โ”‚      โ””โ”€ 1 โ‡’ Project.toml                                  โ”‚
โ”‚                 โ”‚                            โ”‚                               โ”‚
โ”‚       โ”‚          โ””โ”€ 3 โ‡’ nothing => "make.jl"                                 โ”‚
โ”‚                 โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                               โ”‚
โ”‚       โ”‚                 โ””โ”€ 1 โ‡’ make.jl                                       โ”‚
โ”‚                                                                              โ”‚
โ”‚       โ”œโ”€ ๐Ÿ“ build โ‡’ OrderedCollections.OrderedDict("files"                   โ”‚
โ”‚                                                                              โ”‚
โ”‚       โ”‚             => Any[])                                                โ”‚
โ”‚                                                                              โ”‚
โ”‚       โ”‚             โ””โ”€ files โ‡’ Any[]                                         โ”‚
โ”‚                                                                              โ”‚
โ”‚       โ””โ”€ ๐Ÿ“ src โ‡’ OrderedCollections.OrderedDict("files"                     โ”‚
โ”‚                                                                              โ”‚
โ”‚                   => Any[nothing => "index.md", nothing =>                   โ”‚
โ”‚                                                                              โ”‚
โ”‚                   "library.md"])                                             โ”‚
โ”‚                                                                              โ”‚
โ”‚                   โ””โ”€ files โ‡’ Any[nothing => "index.md", nothing =>           โ”‚
โ”‚     "libra                                                                   โ”‚
โ”‚                              ry.md"]                                         โ”‚
โ”‚                                                                              โ”‚
โ”‚                              โ”œโ”€ 1 โ‡’ nothing => "index.md"                    โ”‚
โ”‚                                                                              โ”‚
โ”‚                              โ”‚      โ””โ”€ 1 โ‡’ index.md                          โ”‚
โ”‚                                                                              โ”‚
โ”‚                              โ””โ”€ 2 โ‡’ nothing => "library.md"                  โ”‚
โ”‚                                                                              โ”‚
โ”‚                                     โ””โ”€ 1 โ‡’ library.md                        โ”‚
โ”‚                                                                              โ”‚
โ”‚                                                                              โ”‚
โ”‚                                                                              โ”‚
โ”‚                                                                              โ”‚
โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ

Or get the files/subfolders in your folder

println("Subfolders in folder:")
subdirs(fld-1) |> print
Subfolders in folder:
Folder[Folder("/home/runner/work/ObjectivePaths.jl/ObjectivePaths.jl/docs/build"), Folder("/home/runner/work/ObjectivePaths.jl/ObjectivePaths.jl/docs/src")]
println("Files in folder's parent:")
files(parent(fld)) |> print  # parent goes up one level
Files in folder's parent:
File[File("/home/runner/work/ObjectivePaths.jl/ObjectivePaths.jl/docs/Manifest.toml"), File("/home/runner/work/ObjectivePaths.jl/ObjectivePaths.jl/docs/Project.toml"), File("/home/runner/work/ObjectivePaths.jl/ObjectivePaths.jl/docs/make.jl")]

Manipulating paths

One of the things that can be a bit annoying is manipulating paths. Normally, you'd create a String with the path you need, or you combine things like splitpath and joinpath to create a path. Not fun. We can make things a bit easier.

# say you want to get access to a folder 3 levels up the current one
fld - 3  # done
๐Ÿ“ folder: / > home > runner > work > ObjectivePaths.jl
โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”
exists: โœ” | # files: 1                                 

Yep, that's it. But what if you want to create a new folder in there? Need to split, join paths or something? Nope

newfld = (fld - 3) / "new_folder_that_doesnt_exist_yet"  # point to new folder
๐Ÿ“ folder: / > home > runner > work > ObjectivePaths.jl > new_folder_that_doesn 
t_exist_yet                                                                     
โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”
exists: โœ– |                                                                     

and then you can use mkdir or mkpath as you would normally, neat.

Coda

That's it for now. But if you have issues, or questions or ideas for new improvements, get in touch on Github!

Also, please consider supporting my work if you find it valuable!

ko-fi