【android】oppo手机拷贝视频文件

  • oppo 至今没有一个助手,

  • 有一个助手是升级系统的

  • 有一个connect实际上是做镜像手机屏幕的

  • 当然,也能监控文件变化

  • 对于我有一个camera文件夹2000个文件

  • 导致我每次不开着手机,导出文件到pc经常会断开连接。

  • 然后如果重新connect,会到处一堆xxx(1) 这样的文件

  • 完全没有什么 断点续传、文件存在检测这样的功能

  • 可见oppo 是没有以顾客为中心啊。

  • 插入usb传输文件后,

  • copilot 帮写了一个检测文件名是否存在,存在则复制到我的备份磁盘,不存在,那么跳过的代码:

dump_videos.py

  • D:\XTRANS\cuda\03-graph-db\04-cmkg\phone\dump_videos.py
python 复制代码
import win32com.client
import os
import time

def list_and_copy_videos(device_name, path_components, dest_root=None):
    shell = win32com.client.Dispatch("Shell.Application")
    # 17 = ssfDRIVES (This PC / My Computer)
    computer = shell.NameSpace(17)

    # Destination setup
    dest_shell_folder = None
    if dest_root:
        if not os.path.exists(dest_root):
            try:
                os.makedirs(dest_root)
            except OSError as e:
                print(f"Error creating destination directory '{dest_root}': {e}")
                return

        # Get Shell Folder for destination
        dest_shell_folder = shell.NameSpace(dest_root)
        if not dest_shell_folder:
            print(f"Error: Could not get ShellFolder for '{dest_root}'")
            return
        print(f"Destination folder ready: {dest_root}")

    current_folder = None

    # 1. Find the device in "This PC"
    print(f"Searching for device: {device_name} in 'This PC'...")
    # Note: If executed in a non-interactive session, ensure Shell.Application is available.

    found_device = False
    for item in computer.Items():
        # Using simple Name match. Sometimes display name might vary slightly.
        if item.Name == device_name:
            current_folder = item.GetFolder
            found_device = True
            break

    if not found_device:
        print(f"Error: Device '{device_name}' not found.")
        print("Available devices/drives (in 'This PC'):")
        for item in computer.Items():
            print(f" - {item.Name}")
        return

    # 2. Traverse the path components
    print(f"Device found. Navigating path: {' -> '.join(path_components)}")
    for component in path_components:
        found = False
        items = current_folder.Items()
        for item in items:
             if item.Name == component:
                 # Check if it is a folder. Note: Some MTP folders might report weird types, but IsFolder works usually.
                 if item.IsFolder:
                    current_folder = item.GetFolder
                    found = True
                    break

        if not found:
            print(f"Error: Folder '{component}' not found in '{current_folder.Title}'.")
            print("Available items in current folder:")
            for item in items:
                 # Only printing folders to reduce noise, or first 20 items
                 print(f" - {item.Name} {'[Dir]' if item.IsFolder else ''}")
            return

    print(f"Target folder reached: {current_folder.Title}")

    # 3. Recursively list and copy videos
    output_file = "video_list_3.txt"
    print(f"Scanning for videos (MOV, MP4, MKV, AVI, etc)...")

    if dest_root:
        print(f"Syncing to {dest_root}")

    video_extensions = (
        '.mov', '.mp4', '.m4v',
        '.mkv', '.webm', '.avi',
        '.3gp', '.ts', '.flv',
        '.wmv', '.asf'
    )

    stats = {
        'found': 0,
        'copied': 0,
        'skipped': 0,
        'errors': 0
    }

    found_videos_paths = []

    def recursive_scan(folder, relative_path):
        try:
            items = folder.Items()
        except Exception as e:
            print(f"Access denied or error reading folder {relative_path}: {e}")
            return

        for item in items:
            try:
                if item.IsFolder:
                    new_path = os.path.join(relative_path, item.Name)
                    # print(f"Scanning: {new_path}")
                    recursive_scan(item.GetFolder, new_path)
                else:
                    name = item.Name
                    if name.lower().endswith(video_extensions):
                        full_rel_path = os.path.join(relative_path, name)
                        stats['found'] += 1
                        found_videos_paths.append(full_rel_path)

                        if dest_root and dest_shell_folder:
                            # Flattened unique check: check if filename exists in dest_root
                            # (ignoring relative source path structure for the check, as requested "comparison with E:\...\files")
                            target_path = os.path.join(dest_root, name)

                            if os.path.exists(target_path):
                                print(f"[SKIP] {name} (already exists)")
                                stats['skipped'] += 1
                            else:
                                print(f"[COPY] {name} -> {target_path}")
                                try:
                                    # CopyHere flags:
                                    # 4 (no progress dialog) | 16 (yes to all) | 256 (simple progress)
                                    # Using 256 to show some Windows progress if it takes long, or 0 (default).
                                    # Since we are doing file by file, let's suppress UI if possible (4)
                                    # but MTP copy can be slow.
                                    dest_shell_folder.CopyHere(item, 16) # 16 = Respond to "Yes to All" for any dialog box

                                    # Very crude wait mechanism because CopyHere is async
                                    # Waiting for file to appear
                                    timeout = 60 # seconds
                                    start_wait = time.time()
                                    while not os.path.exists(target_path):
                                        time.sleep(0.5)
                                        if time.time() - start_wait > timeout:
                                            print(f"Warning: Timeout waiting for {name} to appear.")
                                            break

                                    # Optional: Check if size is growing? skipping for speed.
                                    # Just a small sleep to avoid flooding COM
                                    time.sleep(0.5)

                                    if os.path.exists(target_path):
                                         stats['copied'] += 1
                                    else:
                                         stats['errors'] += 1

                                except Exception as copy_err:
                                    print(f"Error copying {name}: {copy_err}")
                                    stats['errors'] += 1

            except Exception as e:
                # Sometimes accessing properties of MTP items fails randomly
                print(f"Error processing item: {e}")

    recursive_scan(current_folder, "")

    with open(output_file, "w", encoding="utf-8") as f:
        for v in found_videos_paths:
            f.write(v + "\n")

    print("-" * 40)
    print(f"Scan & Sync Complete.")
    print(f"Total Found: {stats['found']}")
    print(f"Copied:      {stats['copied']}")
    print(f"Skipped:     {stats['skipped']}")
    print(f"Errors:      {stats['errors']}")
    print(f"List saved to {os.path.abspath(output_file)}")

if __name__ == "__main__":
    # Required: pip install pywin32
    # Phone Name
    DEVICE_NAME = "OPPO Find X8s"

    # Source Path on Phone (MTP uses Names not drive letters)
    PATH_PARTS = ["内部共享存储空间", "DCIM", "Camera"]

    # Target Directory on PC
    # User requested: E:\20260127-视频
    TARGET_DIR = r"E:\20260127-视频"

    list_and_copy_videos(DEVICE_NAME, PATH_PARTS, dest_root=TARGET_DIR)
相关推荐
wanhengidc4 分钟前
《三国志异闻录》搬砖新游戏 云手机
运维·服务器·数据库·游戏·智能手机
Yang-Never28 分钟前
ADB ->adb shell perfetto 抓取 trace 指令
android·开发语言·adb·android studio
johnrui1 小时前
集合与树形结构
开发语言·windows
柯儿的天空2 小时前
【OpenClaw 全面解析:从零到精通】第 006 篇:OpenClaw 在 Windows/WSL2 上的安装与部署实战
人工智能·windows·语言模型·chatgpt·ai作画
2501_937189233 小时前
莫凡电视:地方台专属聚合 稳定直播播放工具
android·源码·源代码管理
阿昭L4 小时前
说说Windows进程的令牌(token)
windows·系统安全·token
耶叶4 小时前
Android 新权限申请模型(Activity Result API)
android
阿拉斯攀登4 小时前
【RK3576 安卓 JNI/NDK 系列 04】JNI 核心语法(下):字符串、数组与对象操作
android·驱动开发·rk3568·瑞芯微·rk安卓驱动·jni字符串操作
2501_915909064 小时前
不用越狱就看不到 iOS App 内部文件?使用 Keymob 查看和导出应用数据目录
android·ios·小程序·https·uni-app·iphone·webview
llxxyy卢5 小时前
web部分中等题目
android·前端