Method for creating new folders?

Need a Method to create new folders. Can’t find any yet.
I can access folder and files to read and write etc. No problem.
What I’m looking for is a Method that will create new folders and sub folders
that do not already exist.
For example:
Within the Special Folder “Documents” create sub folders “Accounts” sub folder “Year1913” add file “TransactionData”.

If anyone cam help I’d be grateful.
Please provide coding for a Method.

George

Check out FolderItem.CreateAsFolder BUT … and this is a common mistake … dont try to create the whole sub path in one shot. It wont work
What do I mean by that ?
Some people try to do
dim f as FolderItem = SpecialFolder.Documents.child("Acccounts/Year1913/TransactionData") if f.exists = false then .....
What you will find is that if Accounts doesn’t exist or year1913 doesn’t exist or transactiondata doesn’t exist you’ll have issues

You should do something like this
And this is NOT perfect code - I’m just illustrating how you do it - there’s no error checking in it

[code]dim f as FolderItem = SpecialFolder.Documents // get the starting folderitem reference

  f = f.child("Accounts") 
 if f.Exists = false then // does the accounts folder exist ?
     // no it doesn't so we want to set out reference to that one
  f= f.createasfolder()  // and create it

end if
f = f.child(“Year1913”)
if f.Exists = false then // does the Year1913 folder exist ?
f= f.createasfolder() // and create it
end if
f = f.child(“TransactionData”)
if f.child(“TransactionData”).Exists = false then // does the Year1913 folder exist ?
f= f.createasfolder() // and create it
end if[/code]

FUNCTION Folder_Path(f as folderitem,path as string)
  dim v() as string
  dim i as integer
  
  if f.child(path).exists then return f.child(path)
  // remove any leading/trailing slashes
  if right(path,1)="/" then path=left(path,len(path)-1) ' cannot have / on the end
 if left(path,1)="/" then path=mid(path,2)
// split on remaining /
  v=split(path,"/")
  for i=0 to v.ubound
    f=f.child(v(i))
    if not f.exists then f.CreateAsFolder()
  next i
  return f
END FUNCTION

f=Folder_Path(specialfolder.documents,“Acccounts/Year1913/TransactionData”)

1 Like

Yeah I wouldn’t do that since you can actually create a dir named “this/is/a/test” as ONE directory named “this/is/a/test”

   dim f as folderitem = SpecialFolder.Desktop
    f= f.child("this/is/a/test")
  
  f.createasFolder

All those funny things people like to do
I have one named “Real Software/Xojo” :stuck_out_tongue:

Thanks Norman & Dave.

Norman, I will try your solution and see how it works out.

If anyone else has any suggestions I would be happy to receive them.

Although it has no checks this works:

dim newFolder as FolderItem

newFolder = SpecialFolder.Documents.child(“Accounts”)
newFolder.CreateAsFolder

newFolder = SpecialFolder.Documents.child(“Accounts”).child(“Year13”)
newFolder.CreateAsFolder

dim f as FolderItem
dim fileStream As TextOutputStream
f = SpecialFolder.Documents.child(“Accounts”).child(“Year13”).child(“StatementData”)
fileStream=TextOutputStream.Create(f)

This creates the new sub folders in the Documents folder and creates the file “StatementsData” in the sub folder “Year13”
This is what I was looking for. All I need to add is the code to check if the folders already exist.

Thanks for pointing me in the right direction to solve my problem.

You don’t need to keep calling SpecialFolder:

dim newFolder as FolderItem

newFolder = SpecialFolder.Documents.child("Accounts")
newFolder.CreateAsFolder

newFolder = newFolder.child("Year13")
newFolder.CreateAsFolder

dim f as FolderItem
dim fileStream As TextOutputStream
f = newFolder.child("StatementData")
fileStream=TextOutputStream.Create(f)

Also, something like this might make your life easier:

Function CreateAsFolderForced(Extends f As FolderItem)
if not f.Parent.Exists then
f.Parent.CreateAsFolderForced
end if
if not f.Exists then
f.CreateAsFolder
end if
End Function

So you could so something like this:

dim newFolder as FolderItem = SpecialFolder.Documents.Child( "Accounts" ).Child( "Year13" )
newFolder.CreateAsFolderForced

Note: I haven’t tested that code.

Thanks Kem.
I can try that to see how it works, but the method I have found has been tested and does work.
It may not be the best method, but it does the job.

Another option on a Mac is to use the shell, the mkdir command has an option to create all intermediate folders:

mkdir -p /full/path/to/your/directory/

Don’t know if there is a corresponding command/option for Windows or Linux

This is an impossible situation. You cannot create a folderitem in a folder that does not exist. f will be nil here.

Worse than that, f itself will be nil. So much for posting code before testing. :-\

I have another idea that I will post shortly.

OK, here’s a method that will work. Description in the comments:

Function CreateAsFolder_MTC(Extends parentFolder As FolderItem, name As String) As FolderItem
  // Ensures that the given folder name exists in the given parent folder.
  // If not, it creates it.
  // Returns the resulting folder.
  
  // Will allow as call like:
  // f = SpecialFolder.Documents.CreateAsFolder_MTC( "folder1" ).CreateAsFolder_MTC( "folder2" )
  
  dim f as FolderItem = parentFolder.Child( name )
  if not f.Exists then
    f.CreateAsFolder
  end if
  
  return f
  
End Function

It’s now part of my M_FolderItem module, hence the appended “_MTC”, and I don’t love “CreateAsFolder” anyway since it will return an existing folder if it’s already there. Open to suggestions.

Ok, so none of those were quite what I was looking for, as I need to be able to make multiple subfolders quickly and easily, but the names will change frequently, so here is my solution:

Function MakeFolder(Str as String) As FolderItem
  Dim Results as FolderItem
  Dim Sh as new Shell
  Dim S as string
  if TargetMacOS then
    s = "mkdir -p " + chr(34) + "/Volumes/" + replaceall(Str,":","/") + chr(34)
  else
    if TargetWin32 then
      S = "mkdir " + chr(34) + Str + chr(34)
    else
      msgbox("Platform Not Supported.")
    end if
  end if
  Sh.Execute(S)
  Results = GetFolderItem(Str,FolderItem.PathTypeAbsolute)
  Return Results
End Function

This is currently configured to run on OS X and Windows only, but you could certainly use similar methods to add additional platforms.

That being said, this obviously makes the code more platform dependent than I would like to have, so if anyone has any better suggestions on how to accomplish the same thing, I would love to hear them.

How about using the folderitem.createasfolder method? This works x-plat and faster as it doesn’t require the shell.

The problem that I have had with createasfolder is that it doesn’t seem to create the entire folder structure.
For example, I need to create the folder:
H:\Temp\Level One\Level Two\2013\October\2014\

In my case, H:\Temp exists, but none of the rest of it, of course the exact folder names and such will vary, but this give an idea.

Dim Tree() As String
#If TargetWin32 Then
Tree = Split(“H:\Temp\Level One\Level Two\2013\October\2014”, “”)
#ElseIf TargetOSX Then
Tree = Split(“HD:Temp:Level One:Level Two:2013:October:2014:”, “:”)
#Else
Tree = Split("/Temp/Level One/Level Two/2013/October/2014/", “/”)
Tree(0) = “/”
#EndIf

Dim f As FolderItem = GetfolderItem(Tree(0))

For i As Integer = 1 to Tree.ubound
If Tree(i) > “” Then
f = f.Child(Tree(i))
If Not f.Exists Then f.CreateAsFolder
End If
Next i

Not tested, but you get the idea.

No it wont work as you are creating one folder and expecting all the others in the tree to be created for you. You will need to traverse down the tree and create each folder within folder.

[quote=13748:@Dave S][code]
FUNCTION Folder_Path(f as folderitem,path as string)
dim v() as string
dim i as integer

if f.child(path).exists then return f.child(path)
// remove any leading/trailing slashes
if right(path,1)="/" then path=left(path,len(path)-1) ’ cannot have / on the end
if left(path,1)="/" then path=mid(path,2)
// split on remaining /
v=split(path,"/")
for i=0 to v.ubound
f=f.child(v(i))
if not f.exists then f.CreateAsFolder()
next i
return f
END FUNCTION
[/code]

f=Folder_Path(specialfolder.documents,“Acccounts/Year1913/TransactionData”)[/quote]
Very good