iT邦幫忙

2021 iThome 鐵人賽

DAY 9
1
Modern Web

整合 Google 服務的燃料——透過 Google Apps Script (GAS) 加速你的工作速度系列 第 9

D9 - 如何用 Google Apps Script 自動化對 Google Drive 的操作?(一)列出所有檔案 ID 與相關資訊

來到了第九天。但一樣先講結論,如果你很急著用,可以直接使用這份 Add-On: Drive Explorer,功能還蠻強大的!自己寫的好處是,如果你想結合其他功能會比較方便。對於想知道怎麼做的人,讓我們開始吧!

今天的目標

現在幾乎每天都會打開 Google Drive,但有時當檔案一多,就會面臨兩個問題——權限設置不清,當一個人加入或離職時,要重複好幾次開開關關。又或是要將不同的線上文件寄信並分享給不同人,這些都會需要知道檔案 ID。有沒有一個快速的方式,可以讓我們抓出特定資料夾內的檔案 ID,並用一個表格管理權限呢?

  1. 要怎麼列出 Google Drive 中的檔案 ID 們?
  2. 要怎麼取得 Google Drive 中的檔案們的權限?
  3. 要怎麼設定 Google Drive 中的檔案們的權限給不同人?

這次的主題我們會分成兩天寫。第一題會在今天跟大家分享,明天會針對第二題與第三題。那我們就開始吧!


Q1. 要怎麼列出 Google Drive 中的檔案 ID 們?

Step 1 開啟 Google Sheet,並串起 GAS

因為我們要用到 Google Sheet ,所以一樣用其作為開啟的管道。借用一下 D8 的影片,來說明怎麼樣開啟一個有連結 GAS 的 Google Sheet。

一樣執行時會有「需要驗證」出現,讓我借用一下 D2 的影片。

Step 2 確認要抓的 Google Drive 位置,並將其 ID 記錄到 GAS 上

這邊我們開一個資料夾,並且在裡面設置一些檔案,其中有一些是有子目錄的。要注意裡面有個「demo」資料夾

那這邊要特別提一下「ID」的概念,每一個 Google 產品都有特定的 ID,位置可以參考這張圖

這邊提供兩種取得方式——

一種是直接從網址上複製,另一種是按右鍵時會出現的。這邊用影片解釋。好,那當我們取得要抓的檔案 ID 後,就是將其丟到 GAS 上,一樣開一個 environment.gs 存放資料。這邊示範完整的流程——

Step 3 讀單一資料夾內的檔案、名稱與ID

在 Google Drive 官方定義的 API 中,主要會將能操作的物件分成三種,分別是 FolderFileUser。會用不同的 API 讀取。

我們來拆解步驟——

  1. 透過 getFolderById() 讀取 Folder
  2. 讀到資料夾後,再接著用 getFiles() 會讀出 files (實際上是 fileIterator,但可以理解成「很多檔案」就是)。
  3. 這個 filesfileIterator)會將這個資料夾內的檔案一個個列出來,這邊我列出它的檔名(getName())和 ID(getId())。

完整程式碼在這——

function readFiles(){
  let folder = DriveApp.getFolderById(drive_ID);
  let files = folder.getFiles();
  let file_arr = []
  while (files.hasNext()) {
    let file = files.next();
    file_arr.push([file.getName(),file.getId()]);
  };
  Logger.log(file_arr);
}

跑起來長這樣——

好那你會發現一個問題,是這邊並沒有列出「資料夾」。仔細一看會發現我們裡面並沒有我們在 Step 2 埋梗的「資料夾」 demo ,那請問我們要如何抓到 demo 與裡面的小資料夾(還有資料)?

Step 4 打開子目錄內的目錄

Step 3 我們是用 getFiles(),這邊我們就帶大家來看看 getFolders() 怎麼樣讀取。

這邊我們要用到的技巧叫做 DP (Dynamic Programming),簡單來說就是(1)在根目錄(或目標位置)執行 DP,去發現子目錄,而(2)進到每個子目錄後,一旦發現還有子子目錄,就會再執行一次 DP,並且不斷重複到找到全部的位置為止。

程式碼長這樣,是直接借用 rpm 在 Stakeholder 的回應:Google apps script - iterate folder and subfolder,覺得寫得很好懂。其中的 getSubFolders(parent) 中還有 getSubFolders(child)的寫法,就是所謂的 DP。

function getSubFolders(parent) {
  parent = parent.getId();
  let childFolder = DriveApp.getFolderById(parent).getFolders();
  while(childFolder.hasNext()) {
    let child = childFolder.next();
    Logger.log(child.getName());
    getSubFolders(child);
  }
  return;
}

function listFolders() {
  let parentFolder = DriveApp.getFolderById(drive_ID);
  let childFolders = parentFolder.getFolders();
  while(childFolders.hasNext()) {
    let child = childFolders.next();
    Logger.log(child.getName());
    getSubFolders(child);
  }
}

好,那執行起來會長什麼樣子呢?(可以參考 Step 2 的架構圖)——

但這樣只有列出「目錄」,又要怎麼樣列出所有檔案,包括子目錄內的檔案呢?讓我們從 Step 5 來看看。

Step 5 列出所有檔案,包括子目錄內的檔案們

這邊就要結合我們的 Step 3 和 Step 4 啦。我們先將 Step 3 改寫成會讀取輸入的 Folder Object 的 function。

function readFilesInFolder(folder){
  let files = folder.getFiles();
  while (files.hasNext()) {
    let file = files.next();
    Logger.log([file.getName(),file.getId()]);
  };
}

接著,在將上面這段放入 Step 4 中。

function getSubFolders(parent) {
  parent = parent.getId();
  let childFolder = DriveApp.getFolderById(parent).getFolders();
  while(childFolder.hasNext()) {
    let child = childFolder.next();
    Logger.log(child.getName());
    readFilesInFolder(child)
    getSubFolders(child);
  }
  return;
}

function listFolders() {
  let parentFolder = DriveApp.getFolderById(drive_ID);
  readFilesInFolder(parentFolder)
  let childFolders = parentFolder.getFolders();
  while(childFolders.hasNext()) {
    let child = childFolders.next();
    Logger.log(child.getName());
    readFilesInFolder(child);
    getSubFolders(child);
  }
}

那接著我們執行看看——

補充的是,有人問說如果是在一進去 Google Drive 的根目錄(沒有 ID 的部分),要怎麼讀?其實就是直接 getFiles() 就行了。這邊是修改 官方範例的程式碼 供大家參考。

function readAllFiles(){
    // Log the name of every file in the user's Drive.
    let files = DriveApp.getFiles();
    while (files.hasNext()) {
      let file = files.next();
      Logger.log(file.getName());
    }
}

一樣按執行就好囉!好,那今天學了...

  1. 檔案 ID 與獲取方式
  2. 檔案列出方式
  3. 資料夾列出方式
  4. 結合檔案與資料夾的列出方式

接著可以將結果參考 D8 寫入 Google Sheet。好,那今天就是我們的 D9,明天 D10 會繼續介紹結合讀取檔案後的操作模式。如果還有問題,透過留言之外,也可以到 Facebook Group,想開很久這次鐵人賽才真的開起來哈哈哈,歡迎來當 Founding Member。如果不想錯過可以訂閱按讚小鈴鐺(?),也歡迎留言跟我說你還想知道什麼做法/主題。我們明天見。


上一篇
D8 - 如何用 Google Apps Script 將 Google Calendar 上的事件與更新全部列出到 Google Sheet 上?
下一篇
D10 - 如何用 Google Apps Script 自動化對 Google Drive 的操作?(二)自動列出所有檔案並設定權限
系列文
整合 Google 服務的燃料——透過 Google Apps Script (GAS) 加速你的工作速度30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言