如何在Ruby中判断两个路径是否指向同一文件夹(Logstash插件场景)
Great question! The confusion with File.identical? comes down to how it checks paths—it compares the actual filesystem entries (like inode numbers for the path itself), not where they resolve to. So if one path is a symlink pointing to the other directory, File.identical? will return false because the symlink is a separate entry with its own inode.
To reliably check if two folder paths point to the same location (even through symlinks, relative paths, or trailing slashes), here are two robust approaches you can use in Logstash's Ruby filter:
Method 1: Resolve paths to their real absolute form
This method normalizes both paths by resolving symlinks, relative components (like ../), and trailing slashes, then compares the resulting absolute paths.
def same_directory?(path1, path2) # First verify both paths exist as directories return false unless File.directory?(path1) && File.directory?(path2) # Resolve to fully qualified, real paths real_path1 = File.realpath(path1) real_path2 = File.realpath(path2) # Compare the normalized paths real_path1 == real_path2 end
Method 2: Compare filesystem device and inode identifiers
This checks if the two directories share the same device and inode numbers (which uniquely identify a filesystem object). File.stat automatically follows symlinks to the target directory, so this works even if one path is a symlink.
def same_directory?(path1, path2) return false unless File.directory?(path1) && File.directory?(path2) dir1_stat = File.stat(path1) dir2_stat = File.stat(path2) # Same device and inode means they're the same directory dir1_stat.dev == dir2_stat.dev && dir1_stat.ino == dir2_stat.ino end
Using this in Logstash's Ruby Filter
Here's how you can implement this in your Logstash config. Let's assume your folder paths are stored in fields folder_path1 and folder_path2:
filter { ruby { code => " def same_directory?(path1, path2) return false unless path1 && path2 # Handle nil values return false unless File.directory?(path1) && File.directory?(path2) real_path1 = File.realpath(path1) real_path2 = File.realpath(path2) real_path1 == real_path2 end # Set a new field indicating if paths are the same event.set('is_same_folder', same_directory?(event.get('folder_path1'), event.get('folder_path2'))) " } }
Key notes:
- Always check if the paths exist as directories first to avoid errors.
- Both methods handle cross-platform cases (Unix/Linux and Windows) correctly.
- Method 1 is more readable, while Method 2 might be slightly faster since it avoids string comparison of full paths.
内容的提问来源于stack exchange,提问作者Loganathan

