I'm developing a python script that will upload files to a specific folder in my drive, as I come to notice, the drive api provides an excellent implementation for that, but I did encountered one problem, how do I delete multiple files at once?
I tried grabbing the files I want from the drive and organize their Id's but no luck there... (a snippet below)
dir_id = "my folder Id"
file_id = "avoid deleting this file"
dFiles = []
query = ""
#will return a list of all the files in the folder
children = service.files().list(q="'"+dir_id+"' in parents").execute()
for i in children["items"]:
print "appending "+i["title"]
if i["id"] != file_id:
#two format options I tried..
dFiles.append(i["id"]) # will show as array of id's ["id1","id2"...]
query +=i["id"]+", " #will show in this format "id1, id2,..."
query = query[:-2] #to remove the finished ',' in the string
#tried both the query and str(dFiles) as arg but no luck...
service.files().delete(fileId=query).execute()
Is it possible to delete selected files (I don't see why it wouldn't be possible, after all, it's a basic operation)?
Thanks in advance!
You can batch multiple Drive API requests together. Something like this should work using the Python API Client Library:
def delete_file(request_id, response, exception):
if exception is not None:
# Do something with the exception
pass
else:
# Do something with the response
pass
batch = service.new_batch_http_request(callback=delete_file)
for file in children["items"]:
batch.add(service.files().delete(fileId=file["id"]))
batch.execute(http=http)
If you delete or trash a folder, it will recursively delete/trash all of the files contained in that folder. Therefore, your code can be vastly simplified:
dir_id = "my folder Id"
file_id = "avoid deleting this file"
service.files().update(fileId=file_id, addParents="root", removeParents=dir_id).execute()
service.files().delete(fileId=dir_id).execute()
This will first move the file you want to keep out of the folder (and into "My Drive") and then delete the folder.
Beware: if you call delete() instead of trash(), the folder and all the files within it will be permanently deleted and there is no way to recover them! So be very careful when using this method with a folder...
Related
I wrote a short function in Google Apps script that can make a copy of a specific file that is stored on Google Drive. The purpose of it is that this file is a template and every time I want to create a new document for work I make a copy of this template and just change the title of the document. The code that I wrote to make a copy of the file and store it in the specific folder that I want is very simple:
function copyFile() {
var file = DriveApp.getFileById("############################################");
var folder = DriveApp.getFolderById("############################");
var filename = "Copy of Template";
file.makeCopy(filename, folder);
}
This function takes a specific file, based on ID and a specific folder based on ID and puts the copy entitles "Copy of Template" into that folder.
I have been searching all over and I cannot seem to find this. Is there a way to do the exact same thing, but using Python instead? Or, at the very least is there a way to have Python somehow call that function to run this function? I need this to be done in Python because I am writing a script that does many functions at once whenever I start a new project for work, such as creating a new document from template in Google Drive as well as other things that are not related to Google Drive at all and they can therefore not be done in Google Apps Script.
There are a few tutorials around the web that give partial answers. Here is a step-by-step guide of what you need to do.
Open Command prompt and type (without the quotes) "pip install PyDrive"
Follow the instructions here by step one - https://developers.google.com/drive/v3/web/quickstart/python to set up an account
When that is done, click on Download JSON and a file will be downloaded. Make sure to rename that to client_secrets.json, not client_secret.json as the Quick Start says to do.
Next, make sure to put that file in the same directory as your python script. If you are running the script from a console, that directory might be your username directory.
I assume that you already know the folder id that you are placing this file in and file id that you are copying. If you don't know it, there are tutorials of how to find it using python or you can open it up in Docs and it will be in the URL of the file. Basically enter the ID of the folder and the ID of the file and when you run this script it will make a copy of the chosen file and place it in the chosen folder.
One thing to note is that while running, your browser window will open up and ask for permission, just click accept and then the script will complete.
In order for this to work you might have to enable the Google Drive API, which is in the API's section.
Python Script:
## Create a new Document in Google Drive
from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive
gauth = GoogleAuth()
gauth.LocalWebserverAuth()
drive = GoogleDrive(gauth)
folder = "########"
title = "Copy of my other file"
file = "############"
drive.auth.service.files().copy(fileId=file,
body={"parents": [{"kind": "drive#fileLink",
"id": folder}], 'title': title}).execute()
From https://developers.google.com/drive/v2/reference/files/copy
from apiclient import errors
# ...
def copy_file(service, origin_file_id, copy_title):
"""Copy an existing file.
Args:
service: Drive API service instance.
origin_file_id: ID of the origin file to copy.
copy_title: Title of the copy.
Returns:
The copied file if successful, None otherwise.
"""
copied_file = {'title': copy_title}
try:
return service.files().copy(
fileId=origin_file_id, body=copied_file).execute()
except errors.HttpError, error:
print 'An error occurred: %s' % error
return None
With API v3:
Copy file to a directory with different name.
service.files().copy(fileId='PutFileIDHere', body={"parents": ['ParentFolderID'], 'name': 'NewFileName'} ).execute()
For me, the answer of #Rashi worked with a small modification.
instead of:
'name': 'NewFileName'
this worked:
'title': 'NewFileName'
I am using the Google Drive's API to create and search files and folders using python 3. Searching a folder is done using the files.list method of the drive API. Each search requires a query q as an input. Some examples of queries are given here. I can successfully search for a folder named hello using its name as given below:
service.files().list(q="name = 'hello'", pageSize=10, fields=files(id, name)).execute()
Now, let us say the ID of the folder is 123, then how can I search for this folder using the ID instead of the name. I have tried replacing q with id = '123' as well as id = 123 but none of it seems to work. The closest query I was able to find here was:
q = "'123' in parents"
But this will return all the files whose parent folder is the folder we are looking for.
Is there any way in which we can directly search folders or files by their ID?
Thank you.
I believe your goal is as follows.
You want to retrieve the folder metadata by the folder ID Drive API with googleapis for python.
In this case, how about the following sample script?
folderId = "###" # Please set the folder ID.
res = service.files().get(fileId=folderId, fields="id, name").execute()
In this case, "Files: get" method is used.
Additional information:
If you want to retrieve the folder list just under the specific folder, you can use the following modified search query.
q = "'123' in parents and mimeType='application/vnd.google-apps.folder'"
In this case, 123 is the top folder ID.
In this modification, the retrieved mimeType is given. By this, only the folder list can be retrieved.
If you want to retrieve the file list except for the folder, you can also use the following search query.
q = "'123' in parents and not mimeType='application/vnd.google-apps.folder'"
If you want to retrieve the folder ID from the folder name, you can use the following sample script. In this case, when there are same folder names of hello, those folders are returned.
res = service.files().list(q="name = 'hello' and mimeType='application/vnd.google-apps.folder'", pageSize=10, fields="files(id, name)").execute()
Note:
In your showing script, please modify fields=files(id, name) of service.files().list(q="name = 'hello'", pageSize=10, fields=files(id, name)).execute() to fields="files(id, name)".
References:
Files: get
Search for files and folders
I would like to iterate over some files in a folder that has its path in databricks Repos.
How would one do this? I don't seem to be able to access the files in Repos
I have added a picture that shows what folders i would like to access (the dbrks & sql folders)
Thanks :)
Image of the repo folder hierarchy
You can read files from repo folders. The path is /mnt/repos/, this is the top folder when opening the repo window. You can then iterate yourself over these files.
Whenever you find the file you want you can read it with (for example) Spark. Example if you want to read a CSV file.
spark.read.format("csv").load(
path, header=True, inferSchema=True, delimiter=";"
)
If you just want to list files in the repositories, then you can use the list command of Workspace REST API. Using it you can implement recursive listing of files. The actual implementation would different, based on your requirements, like, if you need to generate a list of full paths vs. list with subdirectories, etc. This could be something like this (not tested):
import requests
my_pat = "generated personal access token"
workspace_url = "https://name-of-workspace"
def list_files(base_path: str):
lst = requests.request(method='get',
url=f"{workspace_url}/api/2.0/workspace/list",
headers={"Authentication": f"Bearer {my_pat}",
json={"path": base_path}).json()["objects"]
results = []
for i in lst:
if i["object_type"] == "DIRECTORY" or i["object_type"] == "REPO":
results.extend(list_files(i["path"]))
else:
results.append(i["path"])
return results
all_files = list_files("/Repos/<my-initial-folder")
But if you want to read a content of the files in the repository, then you need to use so-called Arbitrary Files support that is available since DBR 8.4.
I have a Sharepoint folder, where every week several files would be dumped. Using python, I would like to download all the files from to a local folder location, do some transformations and upload a single consolidated file back to different location on Sharepoint. But whatever calls I am making, returns an empty JSON file.
Here is the code I have tried till now:
import sharepy
sess = sharepy.connect(site='company.sharepoint.com', username='username', password='password')
site = r'https://company.sharepoint.com/'
path = r'/some-site/Documents/Folder1/Folder2/Folder3/'
r = sess.get(site + """_api/web/GetFolderByServerRelativeUrl('"""+path+"""')/Files""")
r
r.json()['d']['results']
r object is a <Response [200]>.I want to download all the files in Folder3, but it returns empty. If I goto the Sharepoint website, I can see all the files using the same username used to create sess object.
I am getting path variable from the bottom of the details pane. I have tried many other options than GetFolderByServerRelativeUrl, but couldn't seems to be working.
I am new to Python and have no clue about Rest APIs.
Thank you for your help.
You need to get a list of files
# Get list of all files and folders in library
files = s.get("{}/_api/web/lists/GetByTitle('{}')/items?$select=FileLeafRef,FileRef"
.format(site, library)).json()["d"]["results"]
for the complete solution, check this:
https://github.com/JonathanHolvey/sharepy/issues/5
Sorry for my english. I use pydrive for work whith google drive api. I want get list of files. I do it like this:
return self.g_drive.ListFile({'q': 'trashed=false'}).GetList()
this return me list of files. But it list contains delete files. I think 'q': 'trashed=false' it get only exist files, not in the bucket.
How i can get only exist files and files shared with me
Remove the trashed=false and query to get shared files is:
sharedWithMe
Also there is no concept of bucket in google drive
Query to use:
{'q': 'sharedWithMe'}
EDIT
I still believe trashed=false should work
Work around:
There must be a better way but a trick is to do the following:
list_of_trash_files = drive.ListFile({'q': 'trashed=true'})
list_of_all_files = drive.ListFile({'q': ''})
final_required_list = set(list_of_all_files) - set(list_of_trash_files)