The Crystal Programming Language Forum

Problem to get the full path of my program

Hello, I have a tiny problem, in one implementation of my project, I need to get the full path of my program. How can I do that? I don’t found the way.

Depending on your exact need, I’d look into the __DIR__ pseudo constant or Dir.current.

Hmm this don’t solve my problem, the problem is after a Dir.cd, I need to retrieve my origin path of my software, and not where is my path after the Dir.cd command

Can I reset the path after a Dir.cd ?

Could you create a const that represents the root of your project that then wouldn’t be affected by changes in PWD? For example as you have /root/path/src/main.cr:

module MyApp
  ROOT = "#{__DIR__}/../" # => /root/path/
end

EDIT: Er that would be tied to whatever file system you compiled it on. Which is maybe fine?

1 Like

Oh yes good idea.

Because I think I can’t use Process.run in a specific path without a Dir.cd before ?

Process.run has a chdir parameter which does a Dir.cd to that path before executing the command.

Okay, I will do your first solution definitely. Thanks you very much for your help

Would it be better to make more use of relative paths? That way the program itself doesn’t need to be aware of the directory structure of the system its running on.

Uuuuh, it’s very annoying, your answer don’t solve my problem. Because my file for my module containing all of my default paths is located in some directories, my constant ROOT don’t return the good path…

I’m very annoying.

In this case I need to have the full path. Normally I use always relative path.

Look my implementation (where you have the “constant” DIR):

module ISM

    module Option

        class SoftwareSynchronize < ISM::CommandLineOption

            def initialize
                super(  ISM::Default::Option::SoftwareSynchronize::ShortText,
                        ISM::Default::Option::SoftwareSynchronize::LongText,
                        ISM::Default::Option::SoftwareSynchronize::Description,
                        Array(ISM::CommandLineOption).new)
            end

            def start
                synchronizationStartingTime = Time.monotonic
                frameIndex = 0
                reverseAnimation = false
                
                print ISM::Default::Option::SoftwareSynchronize::SynchronizationTitle
                text = ISM::Default::Option::SoftwareSynchronize::SynchronizationWaitingText

                Dir.cd(ISM::Default::Path::SoftwaresDirectory)

                #Pour chaque dépot, utiliser les branches selon la stabilité voulue (stable, testing ...etc)
                Ism.ports.each do |port|
                    currentTime = Time.monotonic

                    if (currentTime - synchronizationStartingTime).milliseconds > 40
                        if frameIndex >= text.size
                            reverseAnimation = true
                        end

                        if frameIndex < 1
                            reverseAnimation = false
                        end

                        if reverseAnimation
                            print "\033[1D"
                            print " "
                            print "\033[1D"
                            frameIndex -= 1
                        end

                        if !reverseAnimation
                            print "#{text[frameIndex].colorize(:green)}"
                            frameIndex += 1
                        end

                        synchronizationStartingTime = Time.monotonic
                    end

                    if !Dir.exists?(port.name)
                        puts port.name
                        Dir.mkdir(port.name)
                        Dir.cd(port.name)
                        Process.run("git",args: ["init"])
                        Process.run("git",args: [   "remote",
                                                    "add",
                                                    "origin",
                                                    port.url])
                    else
                        Dir.cd(port.name)
                    end

                    Process.run("git",args: ["pull","origin","master"])
                    Dir.cd(__DIR__+ISM::Default::Path::SoftwaresDirectory)
                end

                print "#{ISM::Default::Option::SoftwareSynchronize::SynchronizationDoneText.colorize(:green)}\n"
                puts "The database is synchronized"
                    
            end

        end
        
    end

end

Is it possible __DIR__ don’t return the good rooth path because I’m testing the program with the Crystal interpreter ?

Are you looking for Process - Crystal 1.2.2 ?

Won’t work in the interpreter, though.

I checked, if I build or not my program, it’s the same problem, __DIR__ don’t return the path of my program, just the path of the current running code…

Look:

 zohran   master  ~  Documents  Programmation  ISM  crystal Main.cr software -sy
ISM start to synchronizing: SystemBase-CrossToolchain
Unhandled exception: Error while changing directory: '/home/zohran/Documents/Programmation/ISM/ISM/Option/Software/SynchronizeSoftwares/': No such file or directory (File::NotFoundError)
  from /usr/lib64/crystal/crystal/system/unix/dir.cr:52:7 in 'current='
  from /usr/lib64/crystal/dir.cr:147:5 in 'cd'
  from ISM/Option/Software/Synchronize/Synchronize.cr:66:21 in 'start'
  from ISM/Option/Software/Software.cr:23:29 in 'start'
  from ISM/CommandLine.cr:109:25 in 'checkEnteredArguments'
  from ISM/CommandLine.cr:28:13 in 'start'
  from Main.cr:70:1 in '__crystal_main'
  from /usr/lib64/crystal/crystal/main.cr:110:5 in 'main_user_code'
  from /usr/lib64/crystal/crystal/main.cr:96:7 in 'main'
  from /usr/lib64/crystal/crystal/main.cr:119:3 in 'main'
  from /lib64/libc.so.6 in '??'
  from /lib64/libc.so.6 in '__libc_start_main'
  from /home/zohran/.cache/crystal/crystal-run-Main.tmp in '_start'
  from ???

Please define what you mean by “full path of my program”. There are multiple interpretations for that.

Okay, it’s simple. My program actually is located in /home/zohran/Documents/Programmation/ISM/, the full path, and I would like to get it.

But the problem, when my Main.cr is running, __DIR__ return the path of the running code, not the main root path of my project, in my previous post for example, it return /home/zohran/Documents/Programmation/ISM/ISM/Option/Software/SynchronizeSoftwares/, but this path is one of my code source file path, not the Main.cr path

I absolutely need the full path, because I use Dir.cd, and I can’t avoid this command because I need to run a git command

You can retrieve the path by traversing from __DIR__ upward - depending on how many nested directories there are between the current file’s directory and your target path.

For your example, that would be something like Path[__DIR__].parent.parent.parent.

1 Like

No worries finally, for my project I found the best way:
Just don’t use Dir.cd or FileUtils.cd, and use everytime chdir option of Process.run, because when the process is done, it restore the original path.

Definitely better, this can avoid a lot of problem after for my software

Thanks you very much