Skip to content

Instantly share code, notes, and snippets.

@bonelifer
Last active April 23, 2024 20:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bonelifer/6c0dc8e2ea8f371206e197d56f32805d to your computer and use it in GitHub Desktop.
Save bonelifer/6c0dc8e2ea8f371206e197d56f32805d to your computer and use it in GitHub Desktop.
Collection of Python scripts to backup Google Drive files. Created using chatGPT. These are not meant to be sync clients. As such edit docuements online, then download them. This is a one way process to backup your Drive contents locally.
#!/usr/bin/env python3
"""
Script: drive-backup.py
Description: Downloads the entire contents of a Google Drive using Google Drive API.
Requirements:
- Google Client Library: `pip install google-api-python-client`
- Create a project in Google Cloud Console, enable Drive API, and generate credentials (OAuth 2.0 Client IDs).
- Save the credentials JSON file as 'credentials.json' in the same directory as this script.
Usage:
1. Run the script.
"""
import os
from google.oauth2.credentials import Credentials
from googleapiclient.discovery import build
from google.auth.transport.requests import Request
from google_auth_oauthlib.flow import InstalledAppFlow
# If modifying these scopes, delete the file token.json.
SCOPES = ['https://www.googleapis.com/auth/drive.readonly']
def authenticate():
"""
Authenticates user and returns credentials.
"""
creds = None
# The file token.json stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first time.
if os.path.exists('token.json'):
creds = Credentials.from_authorized_user_file('token.json')
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.json', 'w') as token:
token.write(creds.to_json())
return creds
def download_files(service, folder_id, folder_name):
"""
Downloads files recursively from a Google Drive folder.
"""
# Create folder for downloads
if not os.path.exists(folder_name):
os.makedirs(folder_name)
# List files in the folder
results = service.files().list(
q=f"'{folder_id}' in parents",
fields="files(id, name, mimeType)").execute()
items = results.get('files', [])
for item in items:
file_id = item['id']
file_name = item['name']
file_mime_type = item['mimeType']
# Skip Google Apps Scripts
if file_mime_type == 'application/vnd.google-apps.script':
print(f"Skipped Google Apps Script: {file_name}")
continue
# Skip folders
if 'application/vnd.google-apps.folder' in file_mime_type:
# Create a local folder to mirror the Google Drive folder structure
subfolder_name = os.path.join(folder_name, file_name)
if not os.path.exists(subfolder_name):
os.makedirs(subfolder_name)
# Recursively download files from the subfolder
download_files(service, file_id, subfolder_name)
else:
# Download file if it's not a folder or Google Apps file
if not file_mime_type.startswith('application/vnd.google-apps'):
request = service.files().get_media(fileId=file_id)
with open(os.path.join(folder_name, file_name), 'wb') as f:
f.write(request.execute())
print(f"Downloaded: {file_name}")
def main():
creds = authenticate()
service = build('drive', 'v3', credentials=creds)
# Get the root folder ID of Google Drive
root_folder_id = 'root'
# Specify the name of the local folder where files will be downloaded
local_folder_name = 'drive'
download_files(service, root_folder_id, local_folder_name)
if __name__ == '__main__':
main()
#!/usr/bin/env python
"""
Script: gaps-backup.py
Description: Downloads Google Docs, Sheets, and Slides files from Google Drive.
Requirements:
- google-auth
- google-auth-oauthlib
- google-auth-httplib2
- google-api-python-client
- OAuth 2.0 Client ID credentials file named `credentials.json` in the same directory as this script.
Usage:
1. Make sure you have 'credentials.json' with your Google Drive API credentials.
2. Run the script. It will authenticate you through your browser.
3. It will then download Google Docs, Google Sheets, and Google Slides files from the root folder of your Google Drive and save them locally.
Note: This script assumes you have appropriate permissions to access the files.
"""
import os
import pickle
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
# Define the scopes
SCOPES = ['https://www.googleapis.com/auth/drive.readonly']
def authenticate():
"""Authenticate the user and return the credentials."""
creds = None
if os.path.exists('token.pickle'):
with open('token.pickle', 'rb') as token:
creds = pickle.load(token)
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file('credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)
return creds
def download_files(service, folder_id, local_folder_name):
"""Download files from Google Drive."""
if not os.path.exists(local_folder_name):
os.makedirs(local_folder_name)
try:
results = service.files().list(
q=f"'{folder_id}' in parents",
fields="files(id, name, mimeType)").execute()
items = results.get('files', [])
except Exception as e:
print(f"An error occurred while listing files: {e}")
return
if not items:
print('No files found.')
else:
print('Files:')
for item in items:
file_id = item['id']
file_name = item['name']
file_mime_type = item['mimeType']
# Initialize save_folder with None
save_folder = None
# Define download formats based on file type
download_formats = []
if 'application/vnd.google-apps.document' in file_mime_type:
download_formats = [
{'mimeType': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'extension': '.docx'},
{'mimeType': 'application/vnd.oasis.opendocument.text', 'extension': '.odt'},
{'mimeType': 'application/pdf', 'extension': '.pdf'}
]
save_folder = 'local-exported-docs'
elif 'application/vnd.google-apps.spreadsheet' in file_mime_type:
download_formats = [
{'mimeType': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'extension': '.xlsx'},
{'mimeType': 'application/vnd.oasis.opendocument.spreadsheet', 'extension': '.ods'},
{'mimeType': 'application/pdf', 'extension': '.pdf'}
]
save_folder = 'local-exported-sheets'
elif 'application/vnd.google-apps.presentation' in file_mime_type:
download_formats = [
{'mimeType': 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'extension': '.pptx'},
{'mimeType': 'application/vnd.oasis.opendocument.presentation', 'extension': '.odp'},
{'mimeType': 'application/pdf', 'extension': '.pdf'}
]
save_folder = 'local-exported-slides'
# Create subfolder if not empty
if save_folder:
subfolder_path = os.path.join(local_folder_name, save_folder)
if not os.path.exists(subfolder_path):
os.makedirs(subfolder_path)
file_path = os.path.join(subfolder_path, file_name.replace(' ', '_'))
else:
file_path = os.path.join(local_folder_name, file_name.replace(' ', '_'))
# Export Google Docs, Sheets, and Slides files in various formats
for download_format in download_formats:
mime_type = download_format['mimeType']
extension = download_format['extension']
if mime_type and file_path:
request = service.files().export_media(fileId=file_id, mimeType=mime_type)
with open(file_path + extension, 'wb') as f:
f.write(request.execute())
print(f"Downloaded {file_name}{extension}")
def main():
"""Authenticate and download files from Google Drive."""
creds = authenticate()
if creds:
service = build('drive', 'v3', credentials=creds)
root_folder_id = 'root'
local_folder_name = 'drive'
download_files(service, root_folder_id, local_folder_name)
else:
print("Authentication failed.")
if __name__ == '__main__':
main()
#!/usr/bin/env python
"""
Script: shared.py
Description: Downloads shared files, Google Docs, Sheets, and Slides.
Requirements:
- Google API Client Library: `pip install google-api-python-client`
- OAuth 2.0 Client ID credentials file named `credentials.json` in the same directory as this script.
- Enable Google Drive API in the Google Cloud Console and download the credentials.json file.
Usage:
1. Run the script and follow the authorization instructions.
2. Shared files will be downloaded to the 'shared' folder.
3. Docs, Sheets, and Slides will be downloaded to their respective folders.
"""
import os
import json
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
# Scopes for accessing Google Drive API
SCOPES = ['https://www.googleapis.com/auth/drive.readonly']
def authenticate():
"""Authenticate user and return credentials."""
creds = None
# Load token from file if available
if os.path.exists('token.json'):
with open('token.json', 'r') as token:
creds_data = json.load(token) # Load JSON data
creds = Credentials.from_authorized_user_info(creds_data)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file('credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.json', 'w') as token:
token.write(creds.to_json())
return creds
def download_files(service, folder_name):
"""Download files from a specific folder."""
results = service.files().list(q="sharedWithMe=true", fields="files(id, name, mimeType)").execute()
files = results.get('files', [])
# Create base folder if not exist
if not os.path.exists(folder_name):
os.makedirs(folder_name)
for file in files:
file_id = file['id']
file_name = file['name']
mime_type = file['mimeType']
# Determine download format based on MIME type
if 'application/vnd.google-apps.document' in mime_type:
download_formats = [
{'mimeType': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'extension': '.docx'},
{'mimeType': 'application/vnd.oasis.opendocument.text', 'extension': '.odt'},
{'mimeType': 'application/pdf', 'extension': '.pdf'}
]
save_folder = 'shared-exported-docs'
elif 'application/vnd.google-apps.spreadsheet' in mime_type:
download_formats = [
{'mimeType': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'extension': '.xlsx'},
{'mimeType': 'application/vnd.oasis.opendocument.spreadsheet', 'extension': '.ods'},
{'mimeType': 'application/pdf', 'extension': '.pdf'}
]
save_folder = 'shared-exported-sheets'
elif 'application/vnd.google-apps.presentation' in mime_type:
download_formats = [
{'mimeType': 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'extension': '.pptx'},
{'mimeType': 'application/vnd.oasis.opendocument.presentation', 'extension': '.odp'},
{'mimeType': 'application/pdf', 'extension': '.pdf'}
]
save_folder = 'shared-exported-slides'
else:
download_formats = []
save_folder = ''
# Create subfolder if not empty
if save_folder:
subfolder_path = os.path.join(folder_name, save_folder)
if not os.path.exists(subfolder_path):
os.makedirs(subfolder_path)
file_path = os.path.join(subfolder_path, file_name.replace(' ', '_'))
else:
file_path = os.path.join(folder_name, file_name.replace(' ', '_'))
# Export Google Docs, Sheets, and Slides files in various formats
for download_format in download_formats:
mime_type = download_format['mimeType']
extension = download_format['extension']
if mime_type and file_path:
request = service.files().export_media(fileId=file_id, mimeType=mime_type)
# Download file if it doesn't exist or overwrite is enabled
if not os.path.exists(file_path + extension):
with open(file_path + extension, 'wb') as f:
f.write(request.execute())
print(f"Downloaded {file_name}{extension}")
else:
print(f"{mime_type} file '{file_name}' already exists. Skipping...")
# Download shared files if it doesn't exist
if not download_formats:
if not os.path.exists(file_path):
request_shared = service.files().get_media(fileId=file_id)
with open(file_path, 'wb') as f:
f.write(request_shared.execute())
print(f"Downloaded {file_name}")
else:
print(f"Shared file '{file_name}' already exists. Skipping...")
def main():
"""Main function to authenticate and download files."""
# Authenticate user
creds = authenticate()
# Build Google Drive service
service = build('drive', 'v3', credentials=creds)
# Define folders
shared_folder_name = 'drive/shared'
# Download shared files
download_files(service, shared_folder_name)
if __name__ == "__main__":
main()
@bonelifer
Copy link
Author

  1. Enable the APIs in Google Cloud Console:
  • Go to the Google Cloud Console https://console.cloud.google.com/.
  • Click on "APIs & Services" in the navigation menu.
  • Under "Credentials," click on "Create Credentials."
  • Select "OAuth client ID" as the credential type.
  • Choose "Desktop app" as the application type.
  • Give your credentials a name (this won't be visible to users).
  • Click "Create."
  1. Download the credentials file:
  • After creating the credentials, you'll see your Client ID and Secret.
  • Click the "Download JSON" button to download a file named "credentials.json."
  • This file contains sensitive information, so store it securely.
  1. Granting Access (Scopes):
  • By default, these credentials won't have access to Drive or Sheets.
  • To enable access, you'll need to configure the OAuth consent screen within the project settings.
  • In the "Credentials" page, find the newly created credentials and click the edit icon (pencil).
  • Go to the "OAuth consent screen" tab.
  • Click "Edit app" and navigate to the "Scopes" section.
  • Add the following scopes:
    • For Drive access: https://www.googleapis.com/auth/drive
    • For Sheets access: https://www.googleapis.com/auth/spreadsheets
  • Click "Save" after adding the scopes.

Using the credentials.json:

This single credentials.json file can be used to access both Drive and Sheets/Docs APIs in your code. The specific library you use will determine how to reference this file for authentication.

Important Note:

  • Be mindful of security when using these credentials. Don't share them publicly and avoid committing them to version control systems.

For more detailed instructions and code examples, you can refer to the official Google Sheets API quickstart guide: https://www.youtube.com/watch?v=BeIwYBfWPVs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment