从文本文件中的目录列表中读取文件路径并将其存储为批处理脚本中的变量 Windows

Read file path from dir list in text file and store as variable in batch script Windows

目的是 select 使用 Windows 中的批处理脚本从包含文件夹列表的给定文本文件中随机生成一个文件夹。

循序渐进的方法:

  1. 输入主目录路径
  2. 检查当前驱动器号,必要时更改驱动器号以匹配 homedir 驱动器
  3. 将目录更改为主目录
  4. 将目录列表写入主目录HOMEDIR.TXT中的文本文件
  5. SKIP 变量设置为随机数,最多为该文本文件中的行数 到目前为止一切正常
  6. For 没有定界符的循环(所以我得到整行)并跳过 %SKIP% 行数。然后从 for 循环中执行 set VARNAME=%%I 。然后转到 NextLine,这样它就不会重复,直到文本文件的末尾。 ***这一步给我错误:系统找不到指定的文件。

[EDIT] 在进一步测试中,错误仅在 %SKIP% > 4 时发生,即如果 SKIP 对应于带有文件路径的行,它会给出该错误。否则它工作正常。

到处都看了答案,还是解决不了!如果我将 for outside 放入一个只包含随机单词的测试文件中,它就可以正常工作。所以我只能假设它与导致问题的 dir 输出列表中的特殊字符有关?非常感谢任何帮助!

我的代码:

:: Make the code run quietly
@ECHO OFF

:: Get home directory
set HOMEDIR=D:\External\My Pictures

:: Switch to the drive of HOMEDIR
:: If the drive letter of the current directory differs from HOMEDIR
:: Then change drive letter
:: Else change directory to root of that drive
:: Thanks Jatrim for if not 
if not %cd:~0,2% == %HOMEDIR:~0,2% %HOMEDIR:~0,2% else cd %HOMEDIR:~0,2%

:: Change directory to HOMEDIR
cd "%HOMEDIR%"

:: Write a list of the subdirectories of HOMEDIR to file homedir.txt
dir "%cd%" /a:d >> homedir.txt

:: Calculate how many lines there are in homedir.txt
:: Thanks Aacini from 
for /F "" %%I in (homedir.txt) do set /a LINES=%%I
echo LINES=%LINES%

:: enable delayed expansion (needed???)
setlocal EnableDelayedExpansion

:: Set a random integer (within the limit of variable LINES)
:: Thanks Aacini from 
set /a SKIP=%random%%%LINES%
echo SKIP=%SKIP%

:: In homedir.txt the first 5 lines aren't directories
:: SKIP THESE LINES SOMEHOW

:: Thanks Andriy M for the inspiration! 
:: If it's the same as SKIP, read line's contents into variable SCRDIR

for /F "usebackq delims= skip=%SKIP%" %%I in (homedir.txt) do (if not defined SCRDIRORIG set SCRDIRORIG=%%I & GoTo :NextLine)
pause
:NextLine
echo %SCRDIRORIG%
pause

我会推荐这个:

    @echo off &setlocal disabledelayedexpansion
    for /f "tokens=1*delims=:" %%a in ('findstr /n $ homedir.txt') do (
        set ".%%~a.=%%~b"
        set /a DirCount=%%~a
    )
    set /a DirCount-=5
    set /a Sample=%random%%%DirCount
    set /a Sample+=5
    for /f "tokens=1*delims==" %%a in ('set ".%Sample%."') do echo %%~b

对于没有临时文件的版本,您可以尝试使用

@echo off
    setlocal enableextensions disabledelayedexpansion

    set "HOMEDIR=D:\External\My Pictures"

    for /f "tokens=1,*" %%a in ('
        cmd /q /v /c"for /d %%a in ("!HOMEDIR!\*") do (set /a "1000000000+(!random! * %random% %% (!random!+1^)^)" & echo( %%a)"
        ^| sort
        ^| cmd /q /v /c"(set /p "line^=" & echo(!line!)"
    ') do set "SCRDIRORIG=%%b"

    echo Folder selected : %SCRDIRORIG%

代码创建了一个 cmd 实例,它将列出指定起点下的所有文件夹,并以随机数为前缀。对该列表进行排序,然后检索列表中的第一行。

所有这些都包含在 for /f 命令中,因此最后我们可以将起始随机数与文件夹名称分开并设置变量。

我已尝试仔细 select 以下代码中每个步骤的方法以避免陷阱。

  1. 虽然在这里更改为 HOMEDIR 并不是绝对必要的,但最好使用 cd /d 来完成,必要时也可以更改驱动器。
  2. 可以快速创建文件夹列表,从而避免创建临时文件。使用 dir /b /ad 不包括“.”和 '..' 也不会像 dir /ad 这样的任何连接。
  3. 对于计数,使用 find /c 结合对空字符串的否定搜索可直接产生计数,无需复杂的提取(或循环)。
  4. 我们需要在 0..nlines-1 范围内随机跳过几行。一种方法是应用模数运算符 (%),但如果 nlines 为 0,它可能会失败。因此使用替代方法。商 %RANDOM% / 32768 在所需范围 [0..1) 内,所以我们只需要将它与 nlines 相乘即可。
  5. 您必须测试要跳过的零行,否则 FOR 循环将在 skip= 选项上阻塞。
  6. 最后的 FOR 循环提取所需的行并立即以 GOTO 停止。不好但有效。

这是代码:

@echo off &setlocal enableextensions

set "HOMEDIR=D:\External\My Pictures"

cd /d %HOMEDIR%
:: count the dirs
for /f %%I in ('dir /b /ad "%HOMEDIR%"^| find /c /v ""') do set "nlines=%%I"
:: pick a number from 0..nlines-1
set /A nskip=%random% * %nlines% / 32768
:: discard "skip=" option if no lines to skip
set skipopt=
if %nskip% GTR 0 set skipopt=skip=%nskip%
:: read line[nskip+1] from input and quit
for /F "%skipopt% delims=" %%I in ('dir /b /ad %HOMEDIR%') do set "LINE=%%I" & GOTO :out
:out
echo folder selected : %LINE%