-
-
Notifications
You must be signed in to change notification settings - Fork 86
Fix hidden folder checking on Unix-based OS #574
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
Changes from 1 commit
5717941
879a550
db0b71c
bfd4f0e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -52,7 +52,7 @@ public static List<string> GetFiles(string folder, FileScannerConfig config) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| List<string> filteredResult = unfilteredResult | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Ignore hidden files and folders | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .Where(filePath => (!config.ExcludeHiddenFiles || !IsHiddenFile(filePath)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| && (!config.ExcludeHiddenFolders || !IsInsideHiddenFolder(filePath))) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| && (!config.ExcludeHiddenFolders || !IsInsideHiddenFolder(filePath, folder))) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .ToList(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return filteredResult; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -64,10 +64,11 @@ private static bool IsHiddenFile(string filePath) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return Path.GetFileName(filePath).StartsWith("."); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private static bool IsInsideHiddenFolder(string filePath) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private static bool IsInsideHiddenFolder(string filePath, string rootPath) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // On Unix based operating systems, files and folders that start with a dot are hidden. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| string folderPath = Path.GetDirectoryName(filePath); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return folderPath.Contains("\\.") || folderPath.Contains("/."); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Only check for hidden folders that are children of the root path, not the root path itself or its parents. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| string folderPath = Path.GetDirectoryName(filePath).Substring(rootPath.Length); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thank you for tackling this. Consider to wrap rootPath in Besides, performance is relevant here because there can be thousands of files (some users have +20k UltraStar songs). So only wrap it once, not inside the loop. Please test performance with lots of dummy files. Ideally, performance should be similar as before. For example, this repo has several thousand txt files that you can use to test performance https://github.com/Asvarox/allkaraoke
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I agree, seems over engineered. Also performance has to be tested.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm pretty sure
I read that as a promise that the path parameter is always a prefix of any returned file paths. A quick test confirms that if you give it I agree it's not clear from the code that this is the case, so maybe a comment would clarify it. Performance should be about the same as before as
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added a comment for that, as well as fixed a bug where |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return folderPath.StartsWith(".") || folderPath.Contains("\\.") || folderPath.Contains("/."); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| string folderPath = Path.GetDirectoryName(filePath).Substring(rootPath.Length); | |
| return folderPath.StartsWith(".") || folderPath.Contains("\\.") || folderPath.Contains("/."); | |
| string directoryPath = Path.GetDirectoryName(filePath); | |
| if (directoryPath == null) | |
| { | |
| return false; | |
| } | |
| string fullRootPath = Path.GetFullPath(rootPath); | |
| string fullDirectoryPath = Path.GetFullPath(directoryPath); | |
| string relativePath; | |
| try | |
| { | |
| relativePath = Path.GetRelativePath(fullRootPath, fullDirectoryPath); | |
| } | |
| catch | |
| { | |
| // If we cannot compute a relative path, conservatively assume it's not inside a hidden folder under root. | |
| return false; | |
| } | |
| // Exclude the root path itself (".") and any paths that are outside the root (".."). | |
| if (relativePath == "." || | |
| relativePath == ".." || | |
| relativePath.StartsWith(".." + Path.DirectorySeparatorChar) || | |
| relativePath.StartsWith(".." + Path.AltDirectorySeparatorChar)) | |
| { | |
| return false; | |
| } | |
| // Check for hidden folders (segments starting with a dot) in the relative path. | |
| return relativePath.StartsWith(".") | |
| || relativePath.Contains(Path.DirectorySeparatorChar + ".") | |
| || relativePath.Contains(Path.AltDirectorySeparatorChar + "."); |
Copilot
AI
Mar 27, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hidden-folder detection via Contains(\"/.\") / Contains(\"\\\\.\") is brittle and mixes separator conventions; it’s easier to reason about (and less error-prone) if you split the (relative) path into segments and check segment.StartsWith('.') for each segment. If you keep the current approach, StartsWith(\".\") likely won’t match when the relative path begins with a separator (e.g., \"/.config\"), so consider trimming leading directory separators before applying StartsWith.
| return folderPath.StartsWith(".") || folderPath.Contains("\\.") || folderPath.Contains("/."); | |
| // Normalize the relative folder path and check each segment for a leading dot. | |
| if (string.IsNullOrEmpty(folderPath)) | |
| { | |
| return false; | |
| } | |
| folderPath = folderPath.TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); | |
| if (folderPath.Length == 0) | |
| { | |
| return false; | |
| } | |
| string[] segments = folderPath.Split( | |
| new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }, | |
| StringSplitOptions.RemoveEmptyEntries); | |
| return segments.Any(segment => segment.StartsWith(".")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be nice to have a common method for this. Currently, it is duplicated across DirectoryScanner and FileScanner.
Consider a HiddenFolderChecker or similar.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FileScanner and DirectoryScanner seem to be duplicates of each other anyway, they could probably be merged.