Creating directory over SFTP on Ruby fails if directory exists already
Asked Answered
M

1

5

How can I create a directory on Ruby via SFTP only when the directory doesn't exist?

I have the following code right now:

Net::SFTP.start( ip, id, :password => pass, :port=> port ) do |sftp|
    sftp.mkdir! remotePath
    sftp.upload!(localPath + localfile, remotePath + remotefile)
end

I have no problem creating the directory the first time but it tries to recreate the same directory even if it already exists and it throws me an error.

Anyone who knows how to do this?

In using fileutils, there is this code like:

 FileUtils.mkdir_p(remotePath) unless File.exists?(remotePath)

Is there any way I could do the same over SFTP?

Mavilia answered 22/5, 2015 at 5:2 Comment(2)
I forgot to mention, and I just noticed that whenever I upload a file using the above code, it only uploads a 1kb file which means it isn't working properly.Mavilia
Everything is working well now!! Thank you so much :) Wish I could upvote already!Mavilia
G
8

In this case, it may be better to simply "ask for forgiveness", then to "ask for permission". It also eliminates a race condition, where you check if the directory exists, discover it doesn't, and then while creating it you error out because it was created by someone else in the meantime.

The following code will work better:

Net::SFTP.start( ip, id, :password => pass, :port=> port ) do |sftp|
    begin
        sftp.mkdir! remotePath
    rescue Net::SFTP::StatusException => e
        # verify if this returns 11. Your server may return
        # something different like 4.
        if e.code == 11
            # directory already exists. Carry on..
        else 
            raise
        end 
    end
    sftp.upload!(localPath + localfile, remotePath + remotefile)
end
Grope answered 22/5, 2015 at 5:21 Comment(7)
Thank you Martin, I'm going to try that! I'll let you know if it works for me. As I said on my comment, I also notice that I wasn't able to upload the file properly..it only shows 1K.Mavilia
You might want to check for a specific status code, rather than ignoring all exceptions.Examine
Thank you! This works for me! Mine returns 4 and whenever it does, I just do the uploading again.Mavilia
If you wonder about the constants: They are defined in Net::SFTP::Constants::StatusCodesCarboni
Nitpick: This can be cleaned up a tad with an "unless" instead of an "if/else". Thank you, this is very helpful!Worldlywise
@ethel agreed, but I wanted to get the comment in therwGrope
This should re-raise e specifically or else it will hide any other Net::SFTP::StatusExceptions that are raised and will raise a generic "RuntimeError" instead.Superiority

© 2022 - 2024 — McMap. All rights reserved.