diff --git a/apps/federatedfilesharing/lib/FederatedShareProvider.php b/apps/federatedfilesharing/lib/FederatedShareProvider.php
index 67089cba9d37cdd07af6baf392dc2c0821d03613..4d93dec18f7f307eb5c59a0e3fd8c5a23c3cce23 100644
--- a/apps/federatedfilesharing/lib/FederatedShareProvider.php
+++ b/apps/federatedfilesharing/lib/FederatedShareProvider.php
@@ -1100,4 +1100,31 @@ class FederatedShareProvider implements IShareProvider {
 
 		return ['remote' => $remote];
 	}
+
+	public function getAllShares(): iterable {
+		$qb = $this->dbConnection->getQueryBuilder();
+
+		$qb->select('*')
+			->from('share')
+			->where(
+				$qb->expr()->orX(
+					$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_REMOTE)),
+					$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_REMOTE_GROUP))
+				)
+			);
+
+		$cursor = $qb->execute();
+		while($data = $cursor->fetch()) {
+			try {
+				$share = $this->createShareObject($data);
+			} catch (InvalidShare $e) {
+				continue;
+			} catch (ShareNotFound $e) {
+				continue;
+			}
+
+			yield $share;
+		}
+		$cursor->closeCursor();
+	}
 }
diff --git a/apps/sharebymail/lib/ShareByMailProvider.php b/apps/sharebymail/lib/ShareByMailProvider.php
index 9bfe5e733f49fe8369c2a2c6f35a534b384e7692..903df175e9cc63c3719867b0c6174a1dc9cf6fac 100644
--- a/apps/sharebymail/lib/ShareByMailProvider.php
+++ b/apps/sharebymail/lib/ShareByMailProvider.php
@@ -1166,4 +1166,29 @@ class ShareByMailProvider implements IShareProvider {
 		return ['public' => $mail];
 	}
 
+	public function getAllShares(): iterable {
+		$qb = $this->dbConnection->getQueryBuilder();
+
+		$qb->select('*')
+			->from('share')
+			->where(
+				$qb->expr()->orX(
+					$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_EMAIL))
+				)
+			);
+
+		$cursor = $qb->execute();
+		while($data = $cursor->fetch()) {
+			try {
+				$share = $this->createShareObject($data);
+			} catch (InvalidShare $e) {
+				continue;
+			} catch (ShareNotFound $e) {
+				continue;
+			}
+
+			yield $share;
+		}
+		$cursor->closeCursor();
+	}
 }
diff --git a/lib/private/Share20/DefaultShareProvider.php b/lib/private/Share20/DefaultShareProvider.php
index aea50dfcdb6e28e1d8a2ebbfb177c69f32f5226f..05b3094e6a20133186ca234c8895fe3fde10dcb7 100644
--- a/lib/private/Share20/DefaultShareProvider.php
+++ b/lib/private/Share20/DefaultShareProvider.php
@@ -1382,4 +1382,30 @@ class DefaultShareProvider implements IShareProvider {
 		}
 
 	}
+
+	public function getAllShares(): iterable {
+		$qb = $this->dbConn->getQueryBuilder();
+
+		$qb->select('*')
+			->from('share')
+			->where(
+				$qb->expr()->orX(
+					$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_USER)),
+					$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_GROUP)),
+					$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_LINK))
+				)
+			);
+
+		$cursor = $qb->execute();
+		while($data = $cursor->fetch()) {
+			try {
+				$share = $this->createShare($data);
+			} catch (InvalidShare $e) {
+				continue;
+			}
+
+			yield $share;
+		}
+		$cursor->closeCursor();
+	}
 }
diff --git a/lib/private/Share20/Manager.php b/lib/private/Share20/Manager.php
index 2e8e6f9a3af73a622da390eb1b2777b706afbc51..df537062e4ab1470f7267ca5fd2f9eeb10d193a2 100644
--- a/lib/private/Share20/Manager.php
+++ b/lib/private/Share20/Manager.php
@@ -1671,4 +1671,11 @@ class Manager implements IManager {
 		return true;
 	}
 
+	public function getAllShares(): iterable {
+		$providers = $this->factory->getAllProviders();
+
+		foreach ($providers as $provider) {
+			yield from $provider->getAllShares();
+		}
+	}
 }
diff --git a/lib/public/Share/IManager.php b/lib/public/Share/IManager.php
index 302be5233273c43270db4e1dc4b7535e95ed1429..8bb7291d6baec5ae96a053ea23b96e2e6ac55fd7 100644
--- a/lib/public/Share/IManager.php
+++ b/lib/public/Share/IManager.php
@@ -385,4 +385,16 @@ interface IManager {
 	 */
 	public function shareProviderExists($shareType);
 
+	/**
+	 * @Internal
+	 *
+	 * Get all the shares as iterable to reduce memory overhead
+	 * Note, since this opens up database cursors the iterable should
+	 * be fully itterated.
+	 *
+	 * @return iterable
+	 * @since 18.0.0
+	 */
+	public function getAllShares(): iterable;
+
 }
diff --git a/lib/public/Share/IShareProvider.php b/lib/public/Share/IShareProvider.php
index 6731bf8882b293af3162518d6658f0aa54fbf5fd..c881592826900b1e3f1e668c39f11381f3ee18a3 100644
--- a/lib/public/Share/IShareProvider.php
+++ b/lib/public/Share/IShareProvider.php
@@ -217,4 +217,13 @@ interface IShareProvider {
 	 * @since 12
 	 */
 	public function getAccessList($nodes, $currentAccess);
+
+	/**
+	 * Get all the shares in this provider returned as iterable to reduce memory
+	 * overhead
+	 *
+	 * @return iterable
+	 * @since 18.0.0
+	 */
+	public function getAllShares(): iterable;
 }
diff --git a/tests/lib/Share20/DefaultShareProviderTest.php b/tests/lib/Share20/DefaultShareProviderTest.php
index f5f710cbbd39fec00357c3fbfc6e848dfde4453c..8f725022edaf6c8713517b96651d9282ad50313c 100644
--- a/tests/lib/Share20/DefaultShareProviderTest.php
+++ b/tests/lib/Share20/DefaultShareProviderTest.php
@@ -2742,4 +2742,169 @@ class DefaultShareProviderTest extends \Test\TestCase {
 		$u5->delete();
 		$g1->delete();
 	}
+
+	public function testGetAllShares() {
+		$qb = $this->dbConn->getQueryBuilder();
+
+		$qb->insert('share')
+			->values([
+				'share_type'  => $qb->expr()->literal(\OCP\Share::SHARE_TYPE_USER),
+				'share_with'  => $qb->expr()->literal('sharedWith1'),
+				'uid_owner'   => $qb->expr()->literal('shareOwner1'),
+				'uid_initiator' => $qb->expr()->literal('sharedBy1'),
+				'item_type'   => $qb->expr()->literal('file'),
+				'file_source' => $qb->expr()->literal(42),
+				'file_target' => $qb->expr()->literal('myTarget1'),
+				'permissions' => $qb->expr()->literal(13),
+			]);
+		$qb->execute();
+
+		$id1 = $qb->getLastInsertId();
+
+		$qb->insert('share')
+			->values([
+				'share_type'  => $qb->expr()->literal(\OCP\Share::SHARE_TYPE_GROUP),
+				'share_with'  => $qb->expr()->literal('sharedWith2'),
+				'uid_owner'   => $qb->expr()->literal('shareOwner2'),
+				'uid_initiator' => $qb->expr()->literal('sharedBy2'),
+				'item_type'   => $qb->expr()->literal('file'),
+				'file_source' => $qb->expr()->literal(43),
+				'file_target' => $qb->expr()->literal('myTarget2'),
+				'permissions' => $qb->expr()->literal(14),
+			]);
+		$qb->execute();
+
+		$id2 = $qb->getLastInsertId();
+
+		$qb->insert('share')
+			->values([
+				'share_type'  => $qb->expr()->literal(\OCP\Share::SHARE_TYPE_LINK),
+				'token'  => $qb->expr()->literal('token3'),
+				'uid_owner'   => $qb->expr()->literal('shareOwner3'),
+				'uid_initiator' => $qb->expr()->literal('sharedBy3'),
+				'item_type'   => $qb->expr()->literal('file'),
+				'file_source' => $qb->expr()->literal(44),
+				'file_target' => $qb->expr()->literal('myTarget3'),
+				'permissions' => $qb->expr()->literal(15),
+			]);
+		$qb->execute();
+
+		$id3 = $qb->getLastInsertId();
+
+		$qb->insert('share')
+			->values([
+				'share_type'  => $qb->expr()->literal(\OCP\Share::SHARE_TYPE_EMAIL),
+				'share_with'  => $qb->expr()->literal('shareOwner4'),
+				'token'  => $qb->expr()->literal('token4'),
+				'uid_owner'   => $qb->expr()->literal('shareOwner4'),
+				'uid_initiator' => $qb->expr()->literal('sharedBy4'),
+				'item_type'   => $qb->expr()->literal('file'),
+				'file_source' => $qb->expr()->literal(45),
+				'file_target' => $qb->expr()->literal('myTarget4'),
+				'permissions' => $qb->expr()->literal(16),
+			]);
+		$qb->execute();
+
+		$id4 = $qb->getLastInsertId();
+
+		$qb->insert('share')
+			->values([
+				'share_type'  => $qb->expr()->literal(\OCP\Share::SHARE_TYPE_LINK),
+				'token'  => $qb->expr()->literal('token5'),
+				'uid_owner'   => $qb->expr()->literal('shareOwner5'),
+				'uid_initiator' => $qb->expr()->literal('sharedBy5'),
+				'item_type'   => $qb->expr()->literal('file'),
+				'file_source' => $qb->expr()->literal(46),
+				'file_target' => $qb->expr()->literal('myTarget5'),
+				'permissions' => $qb->expr()->literal(17),
+			]);
+		$qb->execute();
+
+		$id5 = $qb->getLastInsertId();
+
+		$ownerPath1 = $this->createMock(File::class);
+		$shareOwner1Folder = $this->createMock(Folder::class);
+		$shareOwner1Folder->method('getById')->willReturn([$ownerPath1]);
+
+		$ownerPath2 = $this->createMock(File::class);
+		$shareOwner2Folder = $this->createMock(Folder::class);
+		$shareOwner2Folder->method('getById')->willReturn([$ownerPath2]);
+
+		$ownerPath3 = $this->createMock(File::class);
+		$shareOwner3Folder = $this->createMock(Folder::class);
+		$shareOwner3Folder->method('getById')->willReturn([$ownerPath3]);
+
+		$ownerPath4 = $this->createMock(File::class);
+		$shareOwner4Folder = $this->createMock(Folder::class);
+		$shareOwner4Folder->method('getById')->willReturn([$ownerPath4]);
+
+		$ownerPath5 = $this->createMock(File::class);
+		$shareOwner5Folder = $this->createMock(Folder::class);
+		$shareOwner5Folder->method('getById')->willReturn([$ownerPath5]);
+
+		$this->rootFolder
+			->method('getUserFolder')
+			->will($this->returnValueMap(
+				[
+					['shareOwner1', $shareOwner1Folder],
+					['shareOwner2', $shareOwner2Folder],
+					['shareOwner3', $shareOwner3Folder],
+					['shareOwner4', $shareOwner4Folder],
+					['shareOwner5', $shareOwner5Folder],
+				]
+			));
+
+		$shares = iterator_to_array($this->provider->getAllShares());
+		$this->assertEquals(4, count($shares));
+
+		$share = $shares[0];
+
+		// We fetch the node so the root folder is eventually called
+
+		$this->assertEquals($id1, $share->getId());
+		$this->assertEquals(\OCP\Share::SHARE_TYPE_USER, $share->getShareType());
+		$this->assertEquals('sharedWith1', $share->getSharedWith());
+		$this->assertEquals('sharedBy1', $share->getSharedBy());
+		$this->assertEquals('shareOwner1', $share->getShareOwner());
+		$this->assertEquals($ownerPath1, $share->getNode());
+		$this->assertEquals(13, $share->getPermissions());
+		$this->assertEquals(null, $share->getToken());
+		$this->assertEquals('myTarget1', $share->getTarget());
+
+		$share = $shares[1];
+
+		$this->assertEquals($id2, $share->getId());
+		$this->assertEquals(\OCP\Share::SHARE_TYPE_GROUP, $share->getShareType());
+		$this->assertEquals('sharedWith2', $share->getSharedWith());
+		$this->assertEquals('sharedBy2', $share->getSharedBy());
+		$this->assertEquals('shareOwner2', $share->getShareOwner());
+		$this->assertEquals($ownerPath2, $share->getNode());
+		$this->assertEquals(14, $share->getPermissions());
+		$this->assertEquals(null, $share->getToken());
+		$this->assertEquals('myTarget2', $share->getTarget());
+
+		$share = $shares[2];
+
+		$this->assertEquals($id3, $share->getId());
+		$this->assertEquals(\OCP\Share::SHARE_TYPE_LINK, $share->getShareType());
+		$this->assertEquals(null, $share->getSharedWith());
+		$this->assertEquals('sharedBy3', $share->getSharedBy());
+		$this->assertEquals('shareOwner3', $share->getShareOwner());
+		$this->assertEquals($ownerPath3, $share->getNode());
+		$this->assertEquals(15, $share->getPermissions());
+		$this->assertEquals('token3', $share->getToken());
+		$this->assertEquals('myTarget3', $share->getTarget());
+
+		$share = $shares[3];
+
+		$this->assertEquals($id5, $share->getId());
+		$this->assertEquals(\OCP\Share::SHARE_TYPE_LINK, $share->getShareType());
+		$this->assertEquals(null, $share->getSharedWith());
+		$this->assertEquals('sharedBy5', $share->getSharedBy());
+		$this->assertEquals('shareOwner5', $share->getShareOwner());
+		$this->assertEquals($ownerPath5, $share->getNode());
+		$this->assertEquals(17, $share->getPermissions());
+		$this->assertEquals('token5', $share->getToken());
+		$this->assertEquals('myTarget5', $share->getTarget());
+	}
 }
diff --git a/tests/lib/Share20/ManagerTest.php b/tests/lib/Share20/ManagerTest.php
index 6f46d69d8df16fc4a55edd4d2a71136df3e8f522..4a7686acd359fa41b61b54dd8d55f19d89e763ef 100644
--- a/tests/lib/Share20/ManagerTest.php
+++ b/tests/lib/Share20/ManagerTest.php
@@ -3685,6 +3685,57 @@ class ManagerTest extends \Test\TestCase {
 		$this->assertSame($expected['users'], $result['users']);
 
 	}
+
+	public function testGetAllShares() {
+		$factory = new DummyFactory2($this->createMock(IServerContainer::class));
+
+		$manager = new Manager(
+			$this->logger,
+			$this->config,
+			$this->secureRandom,
+			$this->hasher,
+			$this->mountManager,
+			$this->groupManager,
+			$this->l,
+			$this->l10nFactory,
+			$factory,
+			$this->userManager,
+			$this->rootFolder,
+			$this->eventDispatcher,
+			$this->mailer,
+			$this->urlGenerator,
+			$this->defaults
+		);
+
+		$factory->setProvider($this->defaultProvider);
+		$extraProvider = $this->createMock(IShareProvider::class);
+		$factory->setSecondProvider($extraProvider);
+
+		$share1 = $this->createMock(IShare::class);
+		$share2 = $this->createMock(IShare::class);
+		$share3 = $this->createMock(IShare::class);
+		$share4 = $this->createMock(IShare::class);
+
+		$this->defaultProvider->method('getAllShares')
+			->willReturnCallback(function() use ($share1, $share2) {
+				yield $share1;
+				yield $share2;
+			});
+		$extraProvider->method('getAllShares')
+			->willReturnCallback(function() use ($share3, $share4) {
+				yield $share3;
+				yield $share4;
+			});
+
+		// "yield from", used in "getAllShares()", does not reset the keys, so
+		// "use_keys" has to be disabled to collect all the values while
+		// ignoring the keys returned by the generator.
+		$result = iterator_to_array($manager->getAllShares(), $use_keys = false);
+
+		$expects = [$share1, $share2, $share3, $share4];
+
+		$this->assertSame($expects, $result);
+	}
 }
 
 class DummyFactory implements IProviderFactory {