AutomationFlowsGeneral › Scheduled Monitoring of New & Modified Files Across Google Drive Folders

Scheduled Monitoring of New & Modified Files Across Google Drive Folders

ByOssian Madisson @ossian on n8n.io

While Google Drive is accessible and easy to use, file listings via API are limited to either all files in the entire Drive or all files in a specific folder. This also means that the n8n triggers for Google Drive are limited to changes to a specific file or folder.

Event trigger★★★★☆ complexity20 nodesGoogle DriveExecute Workflow Trigger
General Trigger: Event Nodes: 20 Complexity: ★★★★☆ Added:

This workflow corresponds to n8n.io template #9209 — we link there as the canonical source.

This workflow follows the Execute Workflow Trigger → Google Drive recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "id": "qOAgdqA9CYJiMqJl",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "TEMPLATE Nested folder recursion",
  "tags": [],
  "nodes": [
    {
      "id": "8fb482bf-81df-48de-b4c0-a04c3a31891d",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -416,
        -592
      ],
      "parameters": {
        "color": 6,
        "width": 1040,
        "height": 496,
        "content": "### Sets root folder to monitor and trigger recursive workflow"
      },
      "typeVersion": 1
    },
    {
      "id": "7657a4a5-9d4c-4c15-83f6-2edf8a40cca3",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -416,
        -80
      ],
      "parameters": {
        "color": 6,
        "width": 1040,
        "height": 448,
        "content": "### Recursively iterates through all nested folders and list their files"
      },
      "typeVersion": 1
    },
    {
      "id": "02300ebf-8389-4a7b-ba79-1977202327ba",
      "name": "Loop all subfolders",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        -96,
        128
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "3f55820c-f4f0-40fb-ac32-4e62b43ea196",
      "name": "List folders",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        128,
        128
      ],
      "parameters": {
        "filter": {
          "folderId": {
            "__rl": true,
            "mode": "id",
            "value": "={{ $json.id }}"
          },
          "whatToSearch": "folders"
        },
        "options": {},
        "resource": "fileFolder",
        "returnAll": true
      },
      "typeVersion": 3,
      "alwaysOutputData": true
    },
    {
      "id": "572e0740-0bec-469d-8f4f-9eec8edb9439",
      "name": "If subfolders exist",
      "type": "n8n-nodes-base.if",
      "position": [
        272,
        128
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "e6a6144c-5c3d-4c15-92e7-147787ece96c",
              "operator": {
                "type": "object",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "9620aee5-78dc-424c-a68e-78c66e67cd51",
      "name": "Trigger recursion to next level",
      "type": "n8n-nodes-base.executeWorkflow",
      "position": [
        464,
        128
      ],
      "parameters": {
        "options": {},
        "workflowId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $workflow.id }}"
        },
        "workflowInputs": {
          "value": {},
          "schema": [
            {
              "id": "folder_name",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "folder_name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "folder_name"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": true
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "e1f951c5-8abd-4f08-ae78-49f20f12c811",
      "name": "List folders in root",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        -64,
        -464
      ],
      "parameters": {
        "filter": {
          "folderId": {
            "__rl": true,
            "mode": "list"
          },
          "whatToSearch": "folders"
        },
        "options": {},
        "resource": "fileFolder",
        "returnAll": true
      },
      "typeVersion": 3,
      "alwaysOutputData": true
    },
    {
      "id": "77e0374f-38cf-4788-9ed6-8af4ad672294",
      "name": "List all files in root",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        -64,
        -272
      ],
      "parameters": {
        "filter": {
          "folderId": {
            "__rl": true,
            "mode": "list"
          },
          "whatToSearch": "files"
        },
        "options": {
          "fields": [
            "*"
          ]
        },
        "resource": "fileFolder",
        "returnAll": true
      },
      "executeOnce": true,
      "typeVersion": 3,
      "alwaysOutputData": true
    },
    {
      "id": "4c07501b-6989-42c5-82ff-f15793e56f84",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -112,
        -544
      ],
      "parameters": {
        "color": 3,
        "width": 288,
        "height": 432,
        "content": "## Instruction: \n### Define root folder in both of these"
      },
      "typeVersion": 1
    },
    {
      "id": "6e141c99-9142-4480-9b31-c5eafcb387ec",
      "name": "Start recursion",
      "type": "n8n-nodes-base.executeWorkflowTrigger",
      "position": [
        -368,
        -16
      ],
      "parameters": {
        "inputSource": "passthrough"
      },
      "typeVersion": 1.1
    },
    {
      "id": "a1d1343a-b0a4-417c-8442-eabec70cb71d",
      "name": "Trigger recursion of first level",
      "type": "n8n-nodes-base.executeWorkflow",
      "position": [
        224,
        -464
      ],
      "parameters": {
        "options": {
          "waitForSubWorkflow": true
        },
        "workflowId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $workflow.id }}"
        },
        "workflowInputs": {
          "value": {},
          "schema": [
            {
              "id": "folder_name",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "folder_name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "folder_name"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": true
        }
      },
      "executeOnce": false,
      "typeVersion": 1.2
    },
    {
      "id": "5b229c5c-5662-460e-a221-19a02efd8863",
      "name": "List all files",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        272,
        -32
      ],
      "parameters": {
        "filter": {
          "folderId": {
            "__rl": true,
            "mode": "id",
            "value": "={{ $json.id }}"
          },
          "whatToSearch": "files"
        },
        "options": {
          "fields": [
            "*"
          ]
        },
        "resource": "fileFolder",
        "returnAll": true
      },
      "typeVersion": 3
    },
    {
      "id": "f6099368-fe4a-4360-9bf6-f7654b1c6a60",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        640,
        -592
      ],
      "parameters": {
        "width": 384,
        "height": 496,
        "content": "### Outputs batches of files created or updated since the last PRODUCTION execution\n*Outputs all files of all nested folders on the first execution*"
      },
      "typeVersion": 1
    },
    {
      "id": "26a7b645-fac2-4f56-94da-d3f447b91d6a",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -368,
        -384
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "minutes",
              "minutesInterval": 60
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "f0e363fe-c83c-47ff-bffd-7368ac9874b5",
      "name": "SetStartTime",
      "type": "n8n-nodes-base.code",
      "position": [
        416,
        -272
      ],
      "parameters": {
        "jsCode": "// Get the last execution timestamp from static data\nconst workflowStaticData = $getWorkflowStaticData('global');\nconst executionStart = $('Schedule Trigger').first().json.timestamp;\n\n// At the end of successful execution, update the timestamp for future comparison\nworkflowStaticData.lastScheduleExecutionStarted = new Date(executionStart).getTime();\n\nreturn [{ json: { lastScheduleExecutionStarted: workflowStaticData.lastScheduleExecutionStarted } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "d53c8060-c97f-4577-a151-4690030cb23f",
      "name": "Outputs new or updated files",
      "type": "n8n-nodes-base.code",
      "position": [
        800,
        -432
      ],
      "parameters": {
        "jsCode": "const recentlyChanged = [];\nconst workflowStaticData = $getWorkflowStaticData('global');\nlet lastScheduleExecutionStarted = workflowStaticData.lastScheduleExecutionStarted;\n\n// Set fallback in case this is the first execution that should return all files found\nif (!lastScheduleExecutionStarted) {\n  lastScheduleExecutionStarted = new Date('2010-01-01').getTime();\n}\n\n// Compare created and update timestamps of each file to see if it's later than the last workflow execution\nfor (const item of $input.all()) {\n  if ( (new Date(item.json.modifiedTime).getTime() > lastScheduleExecutionStarted ) || ( new Date(item.json.createdTime).getTime() > lastScheduleExecutionStarted ) ){\n    recentlyChanged.push(item);\n  }\n}\n\nreturn recentlyChanged;"
      },
      "typeVersion": 2
    },
    {
      "id": "80b1a63f-dfac-4422-8778-d0624b6a5fac",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        640,
        -80
      ],
      "parameters": {
        "color": 5,
        "width": 384,
        "height": 448,
        "content": "## Information\nTemplate created by Smultron Studio (https://smultronstudio.com/en) - feel free to reach out at hello@smultronstudio.com\n\n### Instructions:\n* Set schedule interval in the Schedule Trigger node\n* Connect the Google Drive nodes with your credentials\n* Set your root folder in the two Google Drive nodes in the red box\n\nPlease note that upon the first execution and any manual executions prior to the first **production execution** this will output all files in all folders. \n\nThis workflow will request both a *file listing* and a *folder listing* in the root folder and **ALL** subfolders, may have performance issues when used on huge folder structures. Keep in mind when setting the trigger time."
      },
      "typeVersion": 1
    },
    {
      "id": "728dce31-efc1-44ee-b626-7674c86aaea4",
      "name": "If folders exist",
      "type": "n8n-nodes-base.if",
      "position": [
        -224,
        -16
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "5803397c-7522-4d2c-8118-a8d3da9500df",
              "operator": {
                "type": "object",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2,
      "alwaysOutputData": false
    },
    {
      "id": "17c0b075-9784-4bba-9f5d-d0f00f851271",
      "name": "Exit sub workflow",
      "type": "n8n-nodes-base.set",
      "position": [
        -48,
        -32
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "7dbc41c8-9e5b-4def-bfc4-8fe9e024d70d",
              "name": "status",
              "type": "string",
              "value": "No folders found"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "f2123228-8530-4dc6-8cbb-264bfd7efa3c",
      "name": "Wait for file comparison to complete",
      "type": "n8n-nodes-base.wait",
      "position": [
        256,
        -240
      ],
      "parameters": {},
      "typeVersion": 1.1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "93075173-0789-47dd-8b14-bf6fccfa097d",
  "connections": {
    "List folders": {
      "main": [
        [
          {
            "node": "If subfolders exist",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "SetStartTime": {
      "main": [
        []
      ]
    },
    "List all files": {
      "main": [
        [
          {
            "node": "Outputs new or updated files",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Start recursion": {
      "main": [
        [
          {
            "node": "If folders exist",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If folders exist": {
      "main": [
        [
          {
            "node": "Loop all subfolders",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Exit sub workflow",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "List folders in root",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If subfolders exist": {
      "main": [
        [
          {
            "node": "Trigger recursion to next level",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Loop all subfolders",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop all subfolders": {
      "main": [
        [],
        [
          {
            "node": "List folders",
            "type": "main",
            "index": 0
          },
          {
            "node": "List all files",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "List folders in root": {
      "main": [
        [
          {
            "node": "Trigger recursion of first level",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "List all files in root": {
      "main": [
        [
          {
            "node": "Outputs new or updated files",
            "type": "main",
            "index": 0
          },
          {
            "node": "Wait for file comparison to complete",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Outputs new or updated files": {
      "main": [
        []
      ]
    },
    "Trigger recursion to next level": {
      "main": [
        [
          {
            "node": "Loop all subfolders",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Trigger recursion of first level": {
      "main": [
        [
          {
            "node": "List all files in root",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait for file comparison to complete": {
      "main": [
        [
          {
            "node": "SetStartTime",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

While Google Drive is accessible and easy to use, file listings via API are limited to either all files in the entire Drive or all files in a specific folder. This also means that the n8n triggers for Google Drive are limited to changes to a specific file or folder.

Source: https://n8n.io/workflows/9209/ — original creator credit. Request a take-down →

More General workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

General

Automatically backs up all workflows to Google Drive daily. Triggers daily at 11 PM (or manually on demand) Creates a timestamped backup folder in Google Drive Fetches all workflows from your n8n inst

Google Drive, n8n
General

Schedule Filter. Uses manualTrigger, n8n, splitInBatches, googleDrive. Event-driven trigger; 10 nodes.

n8n, Google Drive
General

Spotify Sync Liked Songs to Playlist. Uses manualTrigger, scheduleTrigger, sort, gotify. Event-driven trigger; 40 nodes.

Gotify, Spotify
General

This template creates a nightly backup of all n8n workflows and saves them to a Google Drive folder. Each night, the previous night's backups are moved to an “n8n_old” folder and renamed with the corr

Move Binary Data, Google Drive, Item Lists +1
General

Code Itemlists. Uses stickyNote, moveBinaryData, googleDrive, itemLists. Scheduled trigger; 33 nodes.

Move Binary Data, Google Drive, Item Lists +1