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

时间:2015-05-26 16:13:35

标签: batch-file text-files filepath

目的是使用Windows中的批处理脚本从包含文件夹列表的给定文本文件中随机选择单个文件夹。

循序渐进的方法:

  1. 输入主目录路径
  2. 检查当前的驱动器号并更改驱动器号以匹配homedir驱动器(如有必要)
  3. 将目录更改为主目录
  4. 将目录列表写入主目录中的文本文件HOMEDIR.TXT
  5. SKIP变量设置为随机数,最多为该文本文件中的行数 一切正常至
  6. 对于没有分隔符的循环(所以我得到整行)并跳过%SKIP%行数。然后从for循环中设置VARNAME = %% I。然后转到NextLine,直到文本文件结束才重复。 ***此步骤导致错误:系统找不到指定的文件。
  7. [编辑]在进一步测试时,错误仅发生在IF%SKIP%> 4即,如果SKIP对应于其上有文件路径的行,则会给出该错误。否则它工作正常。

    我到处都读过所有答案,但无法解决!如果我把外面的内容变成一个只有随机单词的测试文件,它就可以了。所以我只能假设它与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 http://stackoverflow.com/questions/1421441/batch-not-equal-operator
    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 http://stackoverflow.com/questions/13343144/random-line-of-text-ussing-batch
    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 http://stackoverflow.com/questions/13343144/random-line-of-text-ussing-batch
    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! http://stackoverflow.com/questions/6409869/echo-the-nth-line-from-a-text-file-where-n-is-a-command-line-argument
    :: 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
    

3 个答案:

答案 0 :(得分:2)

我建议这样做:

    @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

答案 1 :(得分:0)

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

@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命令中,所以最后我们可以将起始随机数与文件夹名称分开并设置变量。

答案 2 :(得分:0)

我试图为以下代码中的每个步骤仔细选择方法,以避免陷阱。

  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停止。不好但有效。
  7. 以下是代码:

    @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%