Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FTP: Creating Nested Directories Automatically

We are trying to move a file to an FTP site. We need to create a folder structure like this:

/deeply/nested/folder/structure/index.html

Yesterday, we realized we can't create more than one folder at a time, so this doesn't work:

MKD /deeply/nested/folder/structure

So, in code, we wrote a loop that created each folder, one at a time, ignoring errors caused by the folder already existing. Ignoring errors is gross.

Is a way to create these nested folders in one action, rather than multiple? Is there a command to see if a folder already exists? If we just push the file out including the full path, will FTP be smart enough to create the directories for me?

like image 512
Travis Parks Avatar asked Feb 08 '12 13:02

Travis Parks


2 Answers

No, there's no standard way to create a folder with subfolders. There's also no standard way to check if directory exists. You would need to use LIST or MLSD (where supported) and parse the result for this. Can't you just use some third-party component that supports the needed functionality?

like image 82
Eugene Mayevski 'Callback Avatar answered Sep 22 '22 13:09

Eugene Mayevski 'Callback


I wrote a simple C# example here, maybe someone will need this code.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;

namespace Deployer
{
    public class RecursiveFolderUploader
    {
        private const string SrcFullPath = @"C:\prg\Snowinmars\Snowinmars.Ui";
        private readonly IList<string> foldersOnServer;
        private Client ftpClient; // that's your ftp client, init it

        public RecursiveFolderUploader()
        {
            this.foldersOnServer = new List<string>();
        }

        private void UploadAll(DirectoryInfo directoryInfo)
        {
            // ftp://login:[email protected]/path/to/root/mydir/anotherdir/file.dat
            // ^________________uri_______________________^_relevationPath_^
            foreach (var file in directoryInfo.EnumerateFiles())
            {
                if (!file.Directory.FullName.StartsWith(RecursiveFolderUploader.SrcFullPath))
                {
                    throw new InvalidOperationException($"File {file.FullName} is not from {RecursiveFolderUploader.SrcFullPath} folder");
                }

                string relevationPath; // all folders from root up to file

                if (file.Directory.FullName.Length == RecursiveFolderUploader.SrcFullPath.Length)
                {
                    relevationPath = "";
                }
                else
                {
                    relevationPath = file.Directory.FullName.Substring(RecursiveFolderUploader.SrcFullPath.Length, file.Directory.FullName.Length - RecursiveFolderUploader.SrcFullPath.Length);

                    if (relevationPath.StartsWith("\\"))
                    {
                        relevationPath = relevationPath.Remove(0, 1);
                    }
                }

                string destination;
                if (string.IsNullOrWhiteSpace(relevationPath))
                {
                    destination = file.Name;
                }
                else
                {
                    destination = Path.Combine(relevationPath, file.Name).Replace("\\", "/");
                }

                try
                {
                    ftpClient.UploadFile(file.FullName, destination);
                }
                catch (WebException e)
                {
                    // that means that there's no such folder or something else goes wrong
                    // we can check it by creating folders and try again
                    var parts = relevationPath.Replace("\\", "/").Split('/');

                    for (int i = 1; i <= parts.Length; i++)
                    {
                        var path = string.Join("/", parts.Take(i));

                        if (!foldersOnServer.Contains(path))
                        {
                            ftpClient.MakeDirectory(path);
                            foldersOnServer.Add(path);
                        }
                    }

                    try
                    {
                        ftpClient.UploadFile(file.FullName, destination);
                    }
                    catch (Exception innerE)
                    {
                        // if it doesn't help - trouble isn't in folders
                        throw new WebException($"Can't find folder {relevationPath}", innerE);
                    }
                }
            }

            foreach (var directory in directoryInfo.EnumerateDirectories())
            {
                UploadAll(directory);
            }
        }
    }
}
like image 25
homk Avatar answered Sep 18 '22 13:09

homk