Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated to optionally recurse subfolders, fixed bug with special chars #1

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
245 changes: 140 additions & 105 deletions OneDriveVersionCleaner/Program.cs
Original file line number Diff line number Diff line change
@@ -1,69 +1,104 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Security;
using Microsoft.SharePoint.Client;

namespace OneDriveVersionCleaner
{
internal class Program
{
private static void Main(string[] args)
internal class Program
{
// ------------------------------------------------------------------------------------------------------------
// IMPORTANT: This is not production code, and it deletes files from your cloud storage. Use at your own risk!
// ------------------------------------------------------------------------------------------------------------

// TODO: Configure these values.
string webFullUrl = "https://TODO.sharepoint.com/personal/TODO_onmicrosoft_com";
string username = "[email protected]";
SecureString password = new NetworkCredential("", "TODO-ENTER-YOUR-APP-PASSWORD-HERE").SecurePassword; // HACK :)

string[] folderRootRelativeUrls = {
"/Documents/subfolder1",
"/Documents/subfolder1/subfolder11",
"/Documents/subfolder1/subfolder11/subfolder111",
"/Documents/subfolder1/subfolder12",
"/Documents/subfolder2/subfolder21"
};

// --- End of configuration ---

ClientContext context = new ClientContext(webFullUrl)
{
Credentials = new SharePointOnlineCredentials(username, password)
};
context.Load(context.Web);
context.Load(context.Web.Lists);
context.Load(context.Web, web => web.ServerRelativeUrl);
context.ExecuteQuery();
WriteMessage($"Connected to: {context.Web.ServerRelativeUrl}", ConsoleColor.Green);

List list = context.Web.Lists.Single(l => l.Title == "Documents");
context.Load(list);
context.ExecuteQuery();
WriteMessage($"Number of files: {list.ItemCount}", ConsoleColor.Green);

foreach (string rootRelativeUrl in folderRootRelativeUrls)
{
WriteMessage($"\r\nFolder: {rootRelativeUrl}", ConsoleColor.Green);
ProcessFolder(context, list, rootRelativeUrl);
}

WriteMessage("\r\nDone.", ConsoleColor.Green);
}
private static void Main(string[] args)
{
// ------------------------------------------------------------------------------------------------------------
// IMPORTANT: This is not production code, and it deletes files from your cloud storage. Use at your own risk!
// ------------------------------------------------------------------------------------------------------------

// TODO: Configure these values.
string webFullUrl = "https://[custom].sharepoint.com/personal/[custom]";
string username = "[custom your identityhere]";
SecureString password = new NetworkCredential("", "[custom]").SecurePassword; // not secure

string[] folderRootRelativeUrls = {
"/Documents/Code",
"/Documents/YourCustomFoldersHere"
};

bool recurse = true;

// --- End of configuration ---

ClientContext context = new ClientContext(webFullUrl)
{
Credentials = new SharePointOnlineCredentials(username, password)
};
context.Load(context.Web);
context.Load(context.Web.Lists);
context.Load(context.Web, web => web.ServerRelativeUrl);
context.ExecuteQuery();
WriteMessage($"Connected to: {context.Web.ServerRelativeUrl}", ConsoleColor.Green);

List list = context.Web.Lists.Single(l => l.Title == "Documents");
context.Load(list);
context.ExecuteQuery();
WriteMessage($"Number of files: {list.ItemCount}", ConsoleColor.Green);

foreach (var folderToClean in folderRootRelativeUrls)
{
var folderUrls = GetFolderList(context, list, folderToClean, recurse);

foreach (string rootRelativeUrl in folderUrls)
{
WriteMessage($"\r\nFolder: {rootRelativeUrl}", ConsoleColor.Green);
ProcessFolder(context, list, rootRelativeUrl);
}
}

WriteMessage("\r\nDone.", ConsoleColor.Green);
WriteMessage("\r\nPress any key to exit.", ConsoleColor.Green);
Console.ReadKey();
}

private static void ProcessFolder(ClientContext context, List list, string rootRelativeUrl)
{
const int pageSize = 100;
private static List<string> GetFolderList(ClientContext context, List list, string rootRelativeUrl, bool recurse = false, List<string> allFolders = null)
{
if (allFolders == null)
{
allFolders = new List<string>();
}

Folder folder = context.Web.GetFolderByServerRelativePath(ResourcePath.FromDecodedUrl(context.Web.ServerRelativeUrl + rootRelativeUrl));
context.Load(folder);
context.ExecuteQuery();

allFolders.Add(folder.ServerRelativeUrl);

if (recurse)
{
context.Load(folder.Folders);
context.ExecuteQuery();

foreach (var subfolder in folder.Folders)
{
WriteMessage(rootRelativeUrl + '/' + subfolder.Name, ConsoleColor.Yellow);
GetFolderList(context, list, rootRelativeUrl + '/' + subfolder.Name, recurse, allFolders);
}
}

return allFolders;
}

Folder folder = context.Web.GetFolderByServerRelativeUrl(context.Web.ServerRelativeUrl + rootRelativeUrl);
context.Load(folder);
context.ExecuteQuery();
private static void ProcessFolder(ClientContext context, List list, string rootRelativeUrl)
{
const int pageSize = 100;

Folder folder = context.Web.GetFolderByServerRelativePath(ResourcePath.FromDecodedUrl(rootRelativeUrl));
context.Load(folder);
context.ExecuteQuery();

CamlQuery query = new CamlQuery
{
ViewXml = $@"<View>
CamlQuery query = new CamlQuery
{
ViewXml = $@"<View>
<RowLimit>{pageSize}</RowLimit>
<Query>
<Where>
Expand All @@ -74,67 +109,67 @@ private static void ProcessFolder(ClientContext context, List list, string rootR
</Where>
</Query>
</View>",
FolderServerRelativeUrl = folder.ServerRelativeUrl
};
FolderServerRelativeUrl = folder.ServerRelativeUrl
};

bool hasMoreRecords = false;
int pageCount = 1;
bool hasMoreRecords = false;
int pageCount = 1;

do
{
WriteMessage($"\r\nPage: {pageCount}", ConsoleColor.White);
ListItemCollection items = list.GetItems(query);
context.Load(items);
context.ExecuteQuery();
do
{
WriteMessage($"\r\nPage: {pageCount}", ConsoleColor.White);
ListItemCollection items = list.GetItems(query);
context.Load(items);
context.ExecuteQuery();

ProcessItems(context, items);
ProcessItems(context, items);

hasMoreRecords = items.ListItemCollectionPosition != null;
query.ListItemCollectionPosition = items.ListItemCollectionPosition;
hasMoreRecords = items.ListItemCollectionPosition != null;
query.ListItemCollectionPosition = items.ListItemCollectionPosition;

pageCount++;
} while (hasMoreRecords);
}

private static void ProcessItems(ClientContext context, ListItemCollection items)
{
foreach (ListItem item in items)
{
context.Load(item);
context.ExecuteQuery();
ProcessFile(context, item);
}
}

private static void ProcessFile(ClientContext context, ListItem item)
{
File file = item.File;

if (file != null)
{
context.Load(file);
context.Load(file.Versions);
context.ExecuteQuery();
long fileSize = file.Length;
int versionCount = file.Versions.Count;
pageCount++;
} while (hasMoreRecords);
}

if (versionCount > 0)
private static void ProcessItems(ClientContext context, ListItemCollection items)
{
WriteMessage($"File: {file.Name,30}, Version count: {versionCount,5}, Size: {fileSize, 8}, Deleting versions...", ConsoleColor.Gray);
// TODO: file.Versions.DeleteAll();
foreach (ListItem item in items)
{
context.Load(item);
context.ExecuteQuery();
ProcessFile(context, item);
}
}
else

private static void ProcessFile(ClientContext context, ListItem item)
{
WriteMessage($"File: {file.Name,30}, Version count: {versionCount,5}", ConsoleColor.DarkGray);
File file = item.File;

if (file != null)
{
context.Load(file);
context.Load(file.Versions);
context.ExecuteQuery();
long fileSize = file.Length;
int versionCount = file.Versions.Count;

if (versionCount > 0)
{
WriteMessage($"File: {file.Name,30}, Version count: {versionCount,5}, Size: {fileSize,8}, Deleting versions...", ConsoleColor.Gray);
file.Versions.DeleteAll();
}
else
{
WriteMessage($"File: {file.Name,30}, Version count: {versionCount,5}", ConsoleColor.DarkGray);
}
}
}
}
}

private static void WriteMessage(string message, ConsoleColor color)
{
Console.ForegroundColor = color;
Console.WriteLine(message);
Console.ResetColor();
private static void WriteMessage(string message, ConsoleColor color)
{
Console.ForegroundColor = color;
Console.WriteLine(message);
Console.ResetColor();
}
}
}
}