如何判断远程文件路径是否匹配Windows文件资源管理器风格过滤器?
Great question! When building download filtering that aligns with Windows File Explorer's wildcard behavior, here's the most reliable approach tailored to your use case:
1. Lock in Windows Wildcard Rules First
Make sure you’re following the exact logic Windows uses to avoid unexpected mismatches:
?: Matches exactly one arbitrary character (won’t match path separators like/or\—we’ll handle paths in segments to avoid this confusion).*: Matches any number of arbitrary characters (including zero) (also doesn’t cross path separators, so it only targets a single directory/file segment).- Matching is case-insensitive (e.g.,
*.JPGwill matchfilea.jpg).
2. Normalize and Split Paths
Start by standardizing both your remote file paths and filters to use the same path separator (stick with / as in your examples, or switch to \—just be consistent). Then split each path into its individual segments (directories + filename).
For example:
- Remote path:
/folder 1/subfolder 2/filea.jpg→ splits into["folder 1", "subfolder 2", "filea.jpg"] - Filter:
/folder ?/subfolder ?/*.jpg→ splits into["folder ?", "subfolder ?", "*.jpg"]
3. Segment-by-Segment Matching
Windows wildcards don’t work recursively across directories, so you need to match each path segment one-to-one:
- First, check if the number of segments in the remote path matches the filter. If not, skip this filter (e.g., a 3-segment filter can’t match a 4-segment path).
- For each corresponding segment, apply the wildcard match:
- Use system-native APIs if possible (like Windows'
PathMatchSpecWfunction for C/C++ apps)—this guarantees full alignment with File Explorer’s behavior. - For cross-platform or scripted solutions (Python, PowerShell), use a matching function that replicates Windows’ rules.
- Use system-native APIs if possible (like Windows'
Example Python Implementation
Here’s a quick script snippet that handles this logic:
import fnmatch def matches_windows_filter(remote_path, filter_pattern): # Normalize paths and split into segments remote_segments = remote_path.lstrip('/').split('/') filter_segments = filter_pattern.lstrip('/').split('/') # Segment count must match exactly if len(remote_segments) != len(filter_segments): return False # Match each segment (case-insensitive like Windows) for remote_seg, filter_seg in zip(remote_segments, filter_segments): if not fnmatch.fnmatch(remote_seg.lower(), filter_seg.lower()): return False return True # Test with your example paths and filters remote_files = [ "/folder 1/subfolder 2/filea.jpg", "/folder 1/subfolder 2/fileb.pdf", "/folder 1/subfolder 3/filea.jpg" ] filters = [ "/folder ?/subfolder ?/*.jpg", "/*/*/abc.*", "/*/*/*.*" ] for file_path in remote_files: for filter_pat in filters: if matches_windows_filter(file_path, filter_pat): print(f"Download {file_path} (matches filter: {filter_pat})") break else: print(f"Skip {file_path} (no matching filters)")
4. Handle Multiple Filters
Since you have multiple filter patterns, iterate through all of them for each file—if any filter matches, trigger the download.
Key Best Practices
- Use native APIs when possible: Avoid rolling your own matcher if you’re on Windows;
PathMatchSpecis battle-tested and matches File Explorer exactly. - Normalize case: Always convert paths and filters to the same case (lower or upper) to replicate Windows’ case-insensitive behavior.
- Validate segment counts: Don’t let
*trick you into matching across directories—Windows wildcards are non-recursive by design.
内容的提问来源于stack exchange,提问作者Hugo Gonzalez

