I have a local directory which I might add files or remove files. I want to upload added files to Google Drive and remove deleted files from Google Drive as well. These files should be stored within a folder in Google Drive.
To get CREDENTIAL_FILE
(.json), goto Google API Console -> Library
and enable Google Drive API
. Then goto Google API Console -> Credentials -> Create Credential -> OAuth client ID
, I select Other
as Application type
(since I am writing a Python script, not a Web application). Click Download JSON
icon to get the credential json file.
Install Google Client Library.
pip install --upgrade google-api-python-client oauth2client
The following script
- Create a GDrive folder if not already exist
- Query GDrive folder's ID
- Query all files within the GDrive folder
- Query local files in directory and upload files which doesn't exist in GDrive folder
- Delete files in GDrive folder which no longer exist in local directory
from __future__ import print_functionimport osimport globfrom googleapiclient.discovery import buildfrom googleapiclient.http import MediaFileUploadfrom httplib2 import Httpfrom oauth2client import file as oauth2file, client, toolsSCOPES = 'https://www.googleapis.com/auth/drive'CREDENTIAL_FILE = 'gdrive_sync_credential.json'TOKEN_FILE = 'gdrive_sync_token.json'def sync_folder(local_folder, gdrive_folder_name): store = oauth2file.Storage(TOKEN_FILE) creds = store.get() if not creds or creds.invalid: flow = client.flow_from_clientsecrets(CREDENTIAL_FILE, SCOPES) creds = tools.run_flow(flow, store) service = build('drive', 'v3', http=creds.authorize(Http())) drive_service = service file_metadata = { 'name': gdrive_folder_name, 'mimeType': 'application/vnd.google-apps.folder' } response = drive_service.files().list(q="name='{name}' and mimeType='{mimeType}'".format(name=file_metadata['name'], mimeType=file_metadata['mimeType'])).execute() items = response.get('files', []) if not items: print("'{0}'' not found, create new".format(file_metadata['name'])) file = drive_service.files().create(body=file_metadata, fields='id').execute() else: print("'{0}'' found".format(file_metadata['name'])) file = items[0] folder_id = file.get('id') print("folderId={0}".format(folder_id)) # check files on gdrive response = drive_service.files().list(q="'{folderId}' in parents".format(folderId=folder_id)).execute() drive_filenames = {} for _file in response.get('files', []): drive_filenames[_file.get('name')] = _file.get('id') print("drive_filenames={0}".format(len(drive_filenames))) # only upload new files for _file in glob.glob(local_folder + '/*.gz'): filename = os.path.basename(_file) if filename not in drive_filenames: print("Upload {0}".format(filename)) file_metadata = { 'name': filename, 'parents': [folder_id], } media = MediaFileUpload(_file, mimetype='application/gzip') file = drive_service.files().create(body=file_metadata, media_body=media, fields='id').execute() print("Uploaded: {0}".format(file.get('id'))) else: print("{0} Exist".format(filename)) # delete files no longer exist in local for _file, _id in drive_filenames.iteritems(): print("Delete '{0}', {1}".format(_file, _id)) drive_service.files().delete(fileId=_id).execute()
NOTE: The script only check filename, and doesn't reupload file when content changed but filename doesn't change.
NOTE: Web authentication is only required the first time, after which the authorization should be stored in TOKEN_FILE. Web authentication is required again if SCOPES changed.
References: