In Google Drive SDK how do you copy a folder? - google-drive-api

Very simple question. How can I copy a folder with the Google Drive API?
It looks like the file/copy API endpoint doesn't work with folders (though this limitation is not clearly indicated in the documentation).
Of course I could add a second parent to the file, but obviously that's not a solution as most of the time a folder copy is done to do something with it without modifying the original.
So how can I do that? Any idea?

'copy' wouldn't make much sense on a folder. The purpose of copy is to create a second file with the same media content as the first. Since a folder has no media content, 'copy' doesn't really apply.
To answer the question, we need to understand your use case a little. Take a *nix paradigm, "cp -R folder1 folder2" is recursively duplicating all of the files. If that is your use case, you'll need to manually recurse down the tree. If you want the same files to appear in two places, (ie. "ln -s folder1 folder2") then that is done by adding a second parent.

I've published a pypi package to copy a google drive folder. It basically implements the recursive behaviour described in the first answer
https://pypi.org/project/googledrive-cloner/

Related

How to get the file path for a file in google drive for use in colab?

I need the file path for a file stored in Google drive, so I can access it from a Google colab notebook.
E.g.
my_dat = ZipFile('/content/drive/MyDrive/some/file/structure/dat.zip', 'r')
Is there a quick way to "copy as path" or otherwise get the file path to the clipboard as quickly as possible from google drive?
My current method is to manually type up the file path, which is very tedious when doing it repeatedly for files deep down in directories. Basically all I need is a way to quickly and easily have 'MyDrive/some/file/structure/dat.zip' on my clipboard (e.g. similar to here), just without manually typing it.
The best way or really the only way I know of doing this using the Google drive api would be to use the
file.get method, this will return a field called parents. Once you get the parent id you can then do a file get on the parent and continue up until the parent is root. Its going to mean a lot of calls but its the only way I have found to achieve this.
I made my own library to make it easier.
!pip install kora
from kora.drive import get_path
p = get_path(file_id)

Moving a file or folder with DriveApp

Really, there is no way to move a file or folder using the DriveApp class?
From what I could gather on the docs and on the StackOverflow answered questions all proposed implementations seem to copy the file to another location and then delete the original file. That would result in at least two problems:
File/folder having a different folderId on the destination;
File/folder being duplicated and stored indefinitely on Google Vault by retention policy.
I must be doing something wrong. Why is there not a method to simply move the file/folder to another destination (as provided by the Drive Web UI)?
Thanks,
When it comes to moving files with DriveApp, you need to work from the Folder rather than the File.
Open the folder you want to move the file to and use the "addFile(file)" method to add the file to that folder, then open the folder you want to move the file from and use "removeFile(file)" to remove it.
This might seem a bit clunky but it's actually possible to have a file in more than one folder at a time on Drive. The folders are really just labels. When considering a file that is already in multiple folders, the meaning of "moving" it to a new folder is kind of ambiguous, it's really a matter of adding/removing it from folders.
Add:
https://developers.google.com/apps-script/reference/drive/folder#addfilechild
Remove:
https://developers.google.com/apps-script/reference/drive/folder#removeFile(File)
Stumbled across this post (two years & 6 months later) and just wanted to point out that its now possible to do this:
DriveApp.getFileById(myFileId).moveTo(DriveApp.getFolderById(myTargetFolderId));

Drive SDK: locating files in directories

I am using the Google Drive SDK to implement cloud storage for my iOS app. One thing I'm unclear on from the docs is how to query for files deep in the Drive directory structure.
I can make a query like:
title = 'TheFileTitle' and '1234567' in parents
But how to I find the fileID '1234567'? I am creating a directory structure to store my data in the cloud but I only know the subdirectory's name. How do I get the fileID that is needed for this query?
I could query for that directory and look for the fileID in the metadata but that just raises the question again. That directory name may not be unique so I would have to know its parent's fileID to locate the correct one.
Any help clarifying this would be appreciated.
Drive offers very little in the way of folder tree navigation. This is for the very good reason that folders are simply labels attached to files, rather than a strict hierarchy. So for example a file can have two or more parent folders. Although I've never tried it (I'm frightened it would create a black hole and universe would end) it's possible to create a loop where folder-A has child folder-B has child folder-C has child folder-A. Please don't try this at home, kids.
So the answer to your question, is start by querying for all folders and follow their parent arrays to build up an in-memory hierarchy. Then use that to navigate to a given file.
I would also suggest that you ask yourself the question whether deeply nested folders is a good idea. The answer may well be 'yes', but you should at least consider alternatives. Remember, folders were an afterthought in Drive, so might not be all they seem.

Is it possible to retrieve a file or folder resource by path?

Is there any way to get information about a file or folder on Box, given it's full path, but not ID?
For example, I'd like to check if /Foo/Bar/test.txt exists on Box. Currently, I have to start at the root and recursively walk through each folder level, searching for the next segment in the path.
As you can imagine, this process is very cumbersome when writing fully asynchronous code.
There currently is not a way to retrieve files or folders by path. This is something we may consider for the future, but don't have plans to implement it in the short term.

customizing `org-publish-project-alist`

I'm trying to publish webpage using org-mode. Two questions:
Is there a way to "sync" the org-mode files in the base-directory and the html files in the publishing-directory? Specifically, if I delete an org file in the base-directory, can I get org-publish-html to delete the corresponding file in the html directory also?
If I have pages within subdirectories, how can I specify a single .css file in the root directory to be used for the style sheet? For instance, my directory structure is as follows:
public_html/
css/
mystyle.css
index.html
subdir/
index.html
With the following specifications in org-publish-project-alist (this is just a subset) --
:publishing-directory "public_html"
:style "<link rel=\"stylesheet\" href=\"css/mystyle.css\" type=\"text/css\"/>"
mystyle.css is used by public_html/index.html but not by public_html/subdir/index.html. Is there a simple remedy to this (I want the style sheet to be used by both/all files in subdirectories)?
Thanks much ~
There is no straightforward way of doing this. Org-mode doesn't know (or care) about the location to which it is publishing - it just sends things there and makes sure the correct directory structure exists. There is a hook in the publishing process that gets called after the files have been pushed to their published location. This is controlled by setting the :completion-function property in your org-publish-project-alist. You could use this hook to write a function that compares the *.org files in your base-dir and subdirectories to the accompanying *.html published files, and remove those *.html files that don't have an accompanying *.org file.
I suspect this will be most easily accomplished by making your Lisp completion-function call a shell script that removes the necessary files. If you are doing something fancy with the :include, :exclude, or :base-extension properties, you'll likely want your completion-function to grab the pertinent information from the plist and then pass them to your shell script. This org-mode page has an example completion-function that shows how to get property values for the org-publish-project-alist. You would then need to pass them to your shell script.
There are several ways to do this. Perhaps the simplest is to just override the default style sheet in each file with a line such as:
#+STYLE: <link rel="stylesheet" type="text/css" href="../stylesheet.css" />
for your first level of subdirectory files, and keep adding ../ as you get deeper in the directory structure.
Another possibility is generate generic template files for each level within the directory tree. This org-mode page gives a nice example of how to set this up.
Lastly, another option is to use the :preparation-function property of org-publish-project-alist to define a function that will automatically change the style file for each file. Again, this is probably best done by having the Lisp preparation-function call a shell script to parse the files. I could imagine doing this with the Unix sed program to find a regular expression denoted something like href="#MYLOC#/stylesheet.css" /> and substitute the stuff between #'s with the appropriate level within the directory tree. This seems like overkill, given the other options.