如何从 Windows 批处理脚本确定当前用户的文档文件夹的位置?

Tim*_*man 5 windows batch windows-libraries windows-10

我知道我可以使用%userprofile%\Documents,但这仅在文档文件夹仍位于默认位置时才有效。我正在寻找即使用户更改了位置(即从“文档属性”中的“位置”选项卡)也能正常工作的东西。

It *_* Me 5

\n

为什么不直接在 Windows 注册表中读取此信息:

\n

HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders

\n

在此输入图像描述

\n
@echo off && setlocal enabledelayedexpansion\n\nset "_Key_HKCU_Path=HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders"\nset "_Folders_Refer={374DE290-123F-4565-9164-39C4925E467B},Documments,Desktop,Favorites,My Music,My Pictures,My Video,Personal,Programs,Start Menu,Startup"\n\n(for %%i in ("!_Folders_Refer:,=","!")do call :^) %%~i) && endlocal && goto :EOF\n\n:^)\nfor /f tokens^=3* %%i in (\'%__APPDIR__%reg.exe query "!_Key_HKCU_Path!"^|find/i "%~1"\n\')do <con: set "_user_path=%%i%%j" && cmd /v/c "echo\\!_user_path:REG_EXPAND_SZ=! && exit /b"\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  • 输出结果:
  • \n
\n
C:\\Users\\ecker\\Downloads\nC:\\Users\\ecker\\Desktop\nC:\\Users\\ecker\\Favorites\nC:\\Users\\ecker\\Music\nC:\\Users\\ecker\\Pictures\nC:\\Users\\ecker\\Videos\nC:\\Users\\ecker\\Music\nC:\\Users\\ecker\\Pictures\nC:\\Users\\ecker\\Videos\nC:\\Users\\ecker\\Music\nC:\\Users\\ecker\\Pictures\nC:\\Users\\ecker\\Videos\nC:\\Users\\ecker\\Documents\nC:\\Users\\ecker\\AppData\\Roaming\\Microsoft\\Windows\\StartMenu\\Programs\nC:\\Users\\ecker\\AppData\\Roaming\\Microsoft\\Windows\\StartMenu\\Programs\\Startup\nC:\\Users\\ecker\\AppData\\Roaming\\Microsoft\\Windows\\StartMenu\\Programs\nC:\\Users\\ecker\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\nC:\\Users\\ecker\\AppData\\Roaming\\Microsoft\\Windows\\StartMenu\\Programs\\Startup\nC:\\Users\\ecker\\AppData\\Roaming\\Microsoft\\Windows\\StartMenu\\Programs\\Startup\n
Run Code Online (Sandbox Code Playgroud)\n

在此输入图像描述

\n
\n

仅适用于个人/文档文件夹:

\n
@echo off && setlocal enabledelayedexpansion\n\nset "_Key=HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders"\n\nfor /f tokens^=3 %%i in (\'%__APPDIR__%reg.exe query "!_Key!"^|find/i "Personal"\')do <con: call set "_docs_folder=%%~i"\n\nif exist "!_docs_folder!\\My_File.docx" (\n     echo\\!_docs_folder!\\My_File.docx \n     echo\\File exist\n   ) else (\n     echo\\!_docs_folder!\\My_File.docx \n     echo\\File do not exist\n   )\n   \nendlocal && goto :EOF\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  • 输出结果:
  • \n
\n
C:\\Users\\ecker\\Documents\n
Run Code Online (Sandbox Code Playgroud)\n

观察: 1使用<con: callwith将变量( )set "_docs_folder=%%~i"中的完整路径扩展为%%~i%UserProfile%\\DocumentsC:\\Users\\ecker\\Documents

\n

Obs.:2你的代码(带有 / )工作得很好(对于没有空格的用户名/文件夹),它也可以这样写:

\n
@echo off \n\nfor /f tokens^=* %%a in (\'powershell -co [Environment]::GetFolderPath(\'Personal\'^)\n\')do set "docs_folder=%%a" & if exist "%docs_folder%\\*.*" echo\\"%docs_folder%\\*.*"\n
Run Code Online (Sandbox Code Playgroud)\n

在此输入图像描述

\n

考虑使用 all ( *) 标记,因为tokens^=*可以确保循环变量 ( %%i) 中的所有字符都被用来组成变量中的值,包括标准分隔符,例如空格(例如),并且如果用户名包含任何字符,则不包含tokens^=*,实际上只会使用第一个标记(默认情况下),并且在其输出/变量中将缺少其他字符。

\n
\n\n


Tim*_*man 3

我想出了一个适合我的方法:

for /f usebackq %%a in (
    `powershell -command "[Environment]::GetFolderPath('Personal')"`
) do (set "docs_folder=%%a")
echo %docs_folder%
Run Code Online (Sandbox Code Playgroud)

  • 调用 powershell 在批处理文件中执行某些操作有点愚蠢。为什么不在 powershell 中编写整个内容呢? (4认同)