1

I need to add a new file in a nested folder on Google Drive using Google Drive api in the form YYYY/MM/DD/HH/mm/file where the dates are dynamically created basing on the current date. For example:

2021/06/16/11/30/my_file.csv

I created the following script in Python, but it is creating one single folder (named "2021/06/16/11/30") instead of the desired nested structure (multiple nested folders named "06", "11" and "30") inside the parent folder "2021":

from googleapiclient.discovery import build
import google.auth
from googleapiclient.http import MediaFileUpload

SCOPES = ['https://www.googleapis.com/auth/drive.metadata', 'https://www.googleapis.com/auth/drive']

credentials, project_id = google.auth.default(scopes=SCOPES)
service = build('drive', 'v3', credentials=credentials)

folder_id = 'parent-folder-id'

# Create folder
file_metadata = {
    'name': '2021/06/16/11/30',
    'mimeType': 'application/vnd.google-apps.folder',
    'parents': [folder_id],
}
file = service.files().create(body=file_metadata, fields='id').execute()
new_folder_id = file.get('id')
print(f'Folder ID: {new_folder_id}')

# Upload file
file_metadata = {
    'name': 'my_file.csv',
    'parents': [new_folder_id],
}
media = MediaFileUpload('my_file.csv', mimetype='text/csv', resumable=True)
file = service.files().create(body=file_metadata, media_body=media, fields='id').execute()
print(f'Folder ID: {file.get("id")}')

Is there a way to create such nested folder structure in one call instead of iterate on each folder creation and pass the new folder id as new parent id?

3
  • did you try to create folder 2021, next folder 06 in 2021, etc.? Google drive doesn't have to use the same rules as local system. it may treat / as normal char, not separator. Commented Jun 16, 2021 at 18:56
  • To iterate on each folder can solve the issue with the nested structure, but it is causing a new issue, as it creates a new folder every time the command run. Commented Jun 18, 2021 at 13:26
  • then first you has to check if folder exists - it is normal - in normal file system you my also need first check if folder exist before you try to create it because it may raise error. In Linux if you try to create new folder again then you get error. In python standard os.makdirs() raise error when folder exist and you have to check if os.path.exists(). In web drivers is even worst because they may have two folders with the same name because they uses ID to recognize folders. Commented Jun 18, 2021 at 13:43

2 Answers 2

5

Modification points:

  • At Google Drive, each file and folder are managed by the unique ID instead of the filename and folder name. In this case, when the file of my_file.csv is uploaded to the nested folder of 2021/06/16/11/30/, it is required to retrieve the folder ID from the folder name. And, when the folder is not existing, it is required to create new folder.
  • In order to achieve this, unfortunately, the method of service.files().list() is used in a loop. Because it is required to check each folder ID.

When above points are reflected to your script, it becomes as follows.

Modified script:

service = build('drive', 'v3', credentials=credentials)

path = '2021/06/16/11/30' # Please set the path.
folder_id = 'parent-folder-id' # Please set the top folder ID.

# Check the folder structure and create new folder if the folder is not existing.
pathList = path.split('/')
for folder in pathList:
    q = "'" + folder_id + "' in parents and name='" + folder + "' and mimeType='application/vnd.google-apps.folder' and trashed=false"
    files = service.files().list(q=q).execute().get('files')
    if not files:
        file_metadata = {
            'name': folder,
            'mimeType': 'application/vnd.google-apps.folder',
            'parents': [folder_id],
        }
        folder_id = service.files().create(
            body=file_metadata, fields='id').execute().get('id')
    else:
        folder_id = files[0].get('id')

# Upload file
file_metadata = {
    'name': 'my_file.csv',
    'parents': [folder_id],
}
media = MediaFileUpload('my_file.csv', mimetype='text/csv', resumable=True)
file = service.files().create(body=file_metadata, media_body=media, fields='id').execute()
print(f'Folder ID: {file.get("id")}')
  • In this modified script, when the path is path = '2021/06/16/11/30', when the folder is not existing in each folder, the folder is created. When the folder is existing in each folder, new folder is not created.

References:

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you @Tanaike, I tried your solution and it is working fine so I accepted it as best solution. At the moment it seems that Google Drive API have not a smarter way to do it. Thank you again for your effort :)
0

The files.create API creates only one file, and cannot create multiple files on a single call. So to answer your question, you need to create 2021 first, set the newly created folder ID as the parent, then iterate folder creation (06, 16, so on) until you reach the bottom level.

Sample:

folder_id = 'parent-folder-id'

date_array = ["2021", "06", "16", "11", "30"]

for x in date_array:
  # Create folder
  file_metadata = {
      'name': x,
      'mimeType': 'application/vnd.google-apps.folder',
      'parents': [folder_id],
  }
  file = service.files().create(body=file_metadata, fields='id').execute()
  new_folder_id = file.get('id')
  print(f'Folder ID: {new_folder_id}')
  folder_id = new_folder_id

# Upload file
file_metadata = {
    'name': 'my_file.csv',
    'parents': [folder_id],
}
media = MediaFileUpload('my_file.csv', mimetype='text/csv', resumable=True)
file = service.files().create(body=file_metadata, media_body=media, fields='id').execute()
print(f'Folder ID: {file.get("id")}')

1 Comment

Unfortunately this is not a working solution, as it creates all nested directories from scratch every time ... for example it will create a new "2021" table for every day of the year

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.