file_utils.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. import os
  2. import sys
  3. from pathlib import Path
  4. def find_files_by_extension(root_dir, extension):
  5. """
  6. Locates all files with a specific extension within a directory and its subdirectories.
  7. Args:
  8. root_dir (str): The absolute path to the root directory to search.
  9. extension (str): The file extension to look for (e.g., '.unity', '.prefab').
  10. The dot is required.
  11. Returns:
  12. list: A list of absolute paths to the found files.
  13. """
  14. if not extension.startswith('.'):
  15. print("Error: Extension must start with a dot (e.g., '.txt').", file=sys.stderr)
  16. return []
  17. found_files = []
  18. for root, _, files in os.walk(root_dir):
  19. for file in files:
  20. if file.endswith(extension):
  21. found_files.append(os.path.join(root, file))
  22. return found_files
  23. def replicate_directory_structure(source_root, target_root):
  24. """
  25. Copies a directory tree from a source to a target location without copying the files.
  26. Args:
  27. source_root (str): The absolute path of the source directory.
  28. target_root (str): The absolute path of the destination directory.
  29. """
  30. source_root = Path(source_root)
  31. target_root = Path(target_root)
  32. if not source_root.is_dir():
  33. print(f"Error: Source path '{source_root}' is not a valid directory.", file=sys.stderr)
  34. return
  35. for dirpath, _, _ in os.walk(source_root):
  36. # Create a relative path from the source root
  37. relative_path = Path(dirpath).relative_to(source_root)
  38. # Join it with the target root to get the new directory path
  39. target_path = target_root / relative_path
  40. # Create the directory in the target, ignoring if it already exists
  41. target_path.mkdir(parents=True, exist_ok=True)
  42. def create_guid_to_path_map(root_dir):
  43. """
  44. Creates a dictionary mapping GUIDs to their corresponding asset file paths,
  45. scanning both the Assets and Packages directories and ignoring folders.
  46. """
  47. guid_map = {}
  48. scan_dirs = [
  49. os.path.join(root_dir, 'Assets'),
  50. os.path.join(root_dir, 'Packages'),
  51. os.path.join(root_dir, 'Library', 'PackageCache')
  52. ]
  53. for directory in scan_dirs:
  54. if not os.path.isdir(directory):
  55. continue
  56. meta_files = find_files_by_extension(directory, '.meta')
  57. for meta_file_path in meta_files:
  58. asset_path = meta_file_path[:-5]
  59. guid = None
  60. is_folder = False
  61. try:
  62. with open(meta_file_path, 'r', encoding='utf-8') as f:
  63. for line in f:
  64. stripped_line = line.strip()
  65. if stripped_line.startswith('guid:'):
  66. guid = stripped_line.split(':')[1].strip()
  67. if stripped_line == 'folderAsset: yes':
  68. is_folder = True
  69. break
  70. if is_folder:
  71. continue
  72. if guid and guid not in guid_map:
  73. guid_map[guid] = asset_path
  74. except Exception as e:
  75. print(f"Warning: Could not process meta file {meta_file_path}. {e}", file=sys.stderr)
  76. return guid_map
  77. if __name__ == '__main__':
  78. # Example usage for testing the module directly.
  79. # This requires a temporary directory structure to be set up.
  80. # Create a dummy structure for testing
  81. test_source_dir = Path('./tmp_source_for_testing')
  82. test_target_dir = Path('./tmp_target_for_testing')
  83. try:
  84. print("Setting up test directory structure...")
  85. (test_source_dir / 'scenes').mkdir(parents=True, exist_ok=True)
  86. (test_source_dir / 'prefabs' / 'characters').mkdir(parents=True, exist_ok=True)
  87. (test_source_dir / 'scenes' / 'level1.unity').touch()
  88. (test_source_dir / 'scenes' / 'level1.unity.meta').touch()
  89. (test_source_dir / 'prefabs' / 'player.prefab').touch()
  90. print("\n--- Testing find_files_by_extension ---")
  91. unity_files = find_files_by_extension(str(test_source_dir), '.unity')
  92. print(f"Found .unity files: {unity_files}")
  93. assert len(unity_files) == 1
  94. prefab_files = find_files_by_extension(str(test_source_dir), '.prefab')
  95. print(f"Found .prefab files: {prefab_files}")
  96. assert len(prefab_files) == 1
  97. print("\n--- Testing replicate_directory_structure ---")
  98. replicate_directory_structure(str(test_source_dir), str(test_target_dir))
  99. print("Checking replicated structure:")
  100. assert test_target_dir.exists()
  101. assert (test_target_dir / 'scenes').exists()
  102. assert (test_target_dir / 'prefabs' / 'characters').exists()
  103. assert not (test_target_dir / 'scenes' / 'level1.unity').exists() # File should not be copied
  104. print("Replicated structure seems correct.")
  105. finally:
  106. # Clean up test directories
  107. import shutil
  108. if test_source_dir.exists():
  109. shutil.rmtree(test_source_dir)
  110. if test_target_dir.exists():
  111. shutil.rmtree(test_target_dir)
  112. print("\nCleaned up test directories.")