2013-06-12 85 views
1

我已搜索並搜索以找到解決方案(感覺像)一個獨特的問題。許多 這裏的答案已經相當有幫助,讓我走了很長的路,但最後一點讓我難住。批處理文件列出文件夾並允許用戶選擇

  • 我的批處理文件,需要在文件夾中打開一個可執行文件的變量名
  • 此文件夾可能是在兩個中的一個目錄
  • 這是我原本和它的作品

    @ECHO OFF 
    SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION 
    
    SET DIR1="%USERPROFILE%\AppData\Local\Application Workspace\Profiles" 
    SET DIR2=C:\Application\SRW\Profiles 
    
    IF NOT EXIST %DIR1% (
        GOTO PROFILE_2 
    ) ELSE (
        GOTO PROFILE_1 
    ) 
    
    :PROFILE_1 
    for /f "delims=" %%A in ('dir %DIR1% /ad /b') do (
        set foldername=%%~nxA 
        ) 
    SET DIR1=%DIR1:"=% 
    SET DIR=%DIR1%\%foldername%\app.exe 
    GOTO START_APP 
    
    :PROFILE_2 
    for /f "delims=" %%A in ('dir %DIR2% /ad /b') do (
        set foldername=%%~nxA 
        ) 
    SET DIR=%DIR2%\%foldername%\app.exe 
    GOTO START_APP 
    
    :START_APP 
    START "" /b "%DIR%" 
    
    :EOF 
    ENDLOCAL 
    EXIT 
    

然後當我發現某些用戶可能在變量配置文件夾中有多個配置文件時,我被拋出一個曲線球,他們需要能夠選擇哪個一個用於該給定的任務。現在我有一個可變的配置文件文件夾以及該文件夾中的一個或多個變量配置文件。

我發現了代碼來列出文件夾名稱並將它們顯示在命令窗口中進行選擇。

@echo off 
cls 
setlocal EnableDelayedExpansion 

set /a count=0 

for /d %%d in (*) do (
    set /a count+=1 
    @echo !count!. %%d 
) 
setlocal DisableDelayedExpansion 

set /P selection="select folder number:" 

我還發現這個例程允許用戶從列表中選擇一個文件,然後它應該將該文件名稱轉換爲變量。

Batch Script Programming -- How to allow a user to select a file by number from a list of files in a folder?

不幸的是,我不能得到的例子在鏈接的是工作,我不知道如何使它與文件夾名稱的文件夾名稱例如,文件名如工作接近但不足夠接近我瞭解要做什麼。即使它以某種方式確實能夠工作,那麼我怎麼能夠在上面發佈的原始代碼中做這樣的日常工作呢?

另外,如果只有一個文件夾,我真的不希望用戶被強制選擇文件夾。如果只有一個文件夾存在,它應該自動放入文件夾名稱變量中,並且根本沒有任何東西顯示給用戶。

我試圖做什麼甚至可能呢?

任何幫助最受讚賞。

回答

2
@ECHO OFF 
SETLOCAL ENABLEDELAYEDEXPANSION 
:: 
:: Set count-of-targets and application name 
:: 
SET /a targets=0 
SET appname=app.exe 
SET "dots=..." 
:: 
:: clear all "$" variables 
:: 
FOR /f "delims==" %%i IN ('set $ 2^>nul') DO SET "%%i=" 
:: 
:: look for app.exe in (1) userprofile... (2) \application\srw... 
:: 
SET dir1="%USERPROFILE%\AppData\Local\Application Workspace\Profiles" 
SET dir2="C:\Application\SRW\Profiles" 
:: My testing - my directory names 
SET dir1="c:\sourcedir" 
SET dir2="C:\destdir\test dir" 
FOR %%s IN (%dir1% %dir2%) DO (
FOR /f "delims=" %%i IN ('dir /s /b "%%~s\%appname%"') DO (CALL :process "%%~dpi" 
) 
) 
:: 
:: Now have TARGETS=#hits; $_n=full pathname; $n=directoryname 
:: 
IF %targets%==1 SET mychoice=1&GOTO chosen 
:: 
:: repeat a menu 
:: 
:again 
CLS 
FOR /l %%i IN (1,1,%targets%) DO (
IF %%i lss 10 (ECHO(%%i%dots%%dots:~0,1%!$%%i!) ELSE (ECHO(%%i%dots%!$%%i!) 
) 
SET mychoice= 
SET /p mychoice="Please choose 1..%targets% : " 
IF NOT DEFINED $_%mychoice% GOTO again 
:chosen 

CALL SET application="%%$_%mychoice%%%%appname%" 

ECHO START "" /b %application% 

GOTO :EOF 
:: 
:: Parameter is quoted-full-pathname 
:: 
:process 
SET /a targets+=1 
SET $_%targets%=%~1 
SET $=%~1 
FOR %%n IN ("%$:~0,-1%") DO SET $%targets%=%%~nxn 
GOTO :eof 

從你所說的,這應該工作。

第一步是設置。設置找到的目標數量和實際應用程序名稱,並清除所有以「$」開頭的變量名稱。

下一步是指定要使用的目錄。我只是複製你的,然後用設置覆蓋這些設置以適應我的機器 - 當然,你需要刪除那些重要的行。請注意,名稱應設置爲引用...

接下來,從應用程序的每個目錄中掃描。每找到一個實例,請致電:process傳遞完整終止的路徑名。

:process增量發現目標的數量和設置變量$_n來傳遞的全路徑名(未用引號引起),然後設置$的未用引號引起-全路徑名,並使用語法技巧有FOR找到應用程序的即時目錄。 %$:~0,-1%是完整路徑名減去最後一個字符 - \因此結果看起來像一個文件名。然後將該「文件名」分配給$n

一旦目錄掃描完成,%targets%將包含er,即目標數。如果那是1,那麼我們有我們所需要的 - 我們只能選擇目標數字1,所以這是我們選擇的。

否則,清除屏幕並顯示多行 - %targets% to be precise. The format is n ... immediatedirname`,如果目標數小於10,則添加一個額外的點,以便長列表排列良好。 然後詢問一個行號。

此時,唯一存在的$_變量是$_1 .. $_%targets%所以如果$ _%mychoice%存在,它必須是有效的選擇。如果沒有定義,則重複該問題...

CALL ing SET application =「%% $ _%mychoice %%%% appname%」首先解析命令,然後再解析它。第一次解析後,該行將變爲(如果mychoice=3SET application="%$_3%app.exe" so on the second occasion,應用程序被正確設置爲應用程序的完整fulename並且被引用。

我的starting這個應用沒有太多點,因爲它不存在,所以我只是echo編輯它。


考慮到擴展需求:

你可能是從快捷方式啓動了這一點。假設你運行該快捷方式最小化,SETLOCAL

SET "poweruser=%1" 

添加後插入,後

IF %targets%==1 SET mychoice=1&GOTO chosen 

IF NOT DEFINED poweruser START "%username% - poweruser" "%~dpnx0" poweruser&GOTO :EOF 

,並更改

GOTO :EOF 

之前,爲了l阿貝爾:process

EXIT 

,這樣,如果不是在高級用戶模式下運行(因此poweruser定義)和%targets% 1(我假設它不會是0),則此用戶尚未設置爲快捷方式中的超級用戶,但確實有有多個目標,因此作業將以超級用戶模式(即超級用戶模式)重新啓動。最大化。)

請注意,它實際上並不重要,該字符串在"~dpnx0"之後 - 只要它是一個字符串。我剛剛使用poweruser它所做的是告訴批處理,它正在正常窗口中運行,而不是最小化。

對於powerusrs,您可以設置快捷方式爲normal windowmaximised,並在batchname之後的命令行中放入一個參數,這會稍微加快該過程。如果不帶參數並將其最小化,將適合所有用戶,因爲如果找到多個目標,它將自動調整。

我試過這個。它爲我工作。

+0

謝謝!這比我習慣的更復雜,但我一定會嘗試並回報。 – jubilare

+0

這個例程很棒,可以馬上使用。我也很欣賞這個解釋。只有最後一個問題。有沒有辦法使批量運行最小化,除非用戶必須做出選擇?其他例程(如複製文件)將被添加到批處理文件中,我的目標是讓除了那些擁有多個配置文件的高級用戶以外的所有人都看不到它。再次感謝! – jubilare

+0

經過研究,似乎無法在批處理文件中撤消最小化命令。但是,可能會將選擇參數(僅當存在多個文件夾時)傳遞給另一個未設置爲最小化運行的批處理文件。聽起來像很多額外的編碼,但。我會仔細研究這一點。 – jubilare

1

我在兩個步驟中回答了您的問題。在第一個中,我將你的原始代碼翻譯成更可讀的代碼。這裏是:

@ECHO OFF 
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION 

SET "DIR1=%USERPROFILE%\AppData\Local\Application Workspace\Profiles" 
SET DIR2=C:\Application\SRW\Profiles 

IF NOT EXIST "%DIR1%" (
    for /f "delims=" %%A in ('dir %DIR2% /ad /b') do (
     SET DIR=%DIR2%\%%~nxA\app.exe 
    ) 
) ELSE (
    for /f "delims=" %%A in ('dir %DIR1% /ad /b') do (
     SET DIR=%DIR1%\%%~nxA\app.exe 
    ) 
) 

START "" /b "%DIR%" 
ENDLOCAL 
EXIT 

你應該先檢查前面的代碼是否與原來的代碼相同。

在第二步中,我加入了配置文件選擇到以前的代碼:

@ECHO OFF 
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION 

SET "DIR1=%USERPROFILE%\AppData\Local\Application Workspace\Profiles" 
SET DIR2=C:\Application\SRW\Profiles 

IF NOT EXIST "%DIR1%" (
    for /f "delims=" %%A in ('dir %DIR2% /ad /b') do (
     SET DIR=%DIR2%\%%~nxA\app.exe 
    ) 
) ELSE (
    call :SelectProfile 
) 

START "" /b "%DIR%" 
ENDLOCAL 
EXIT 


:SelectProfile 

rem Get a list of folders in User Profile dir 
set count=0 
for /f "delims=" %%A in ('dir %DIR1% /ad /b') do (
    set /A count+=1 
    SET DIR[!count!]=%DIR1%\%%~nxA 
) 

rem Initialize the selected profile 
set select=1 
if %count% equ 1 goto endSelection 

rem Show the profiles menu 
cls 
echo Available profiles: 
echo/ 
for /L %%i in (1,1,%count%) do echo %%i- !DIR[%%i]! 
echo/ 

rem Let's the user to select the profile 
:select 
set select=1 
set /P "select=Enter number of desired profile [first one]: " 
if not defined DIR[!select!] goto select 

:endSelection 
SET DIR=!DIR[%select%]!\app.exe 
exit /B 

請注意,上面的代碼失敗,如果用戶在答案中輸入空格。如果需要,這個細節可能是固定的。

+0

謝謝。我現在嘗試一下並報告。 – jubilare

+0

感謝這兩個例程。我按照你的建議嘗試了第一個,只需做一個小小的更新。我明白你爲什麼用引號括住了DIR1,但它引發了一個錯誤,我不得不將它改回來,然後添加一行代碼以在找到文件夾名稱後刪除引號。我嘗試了第二個例程,並且遇到同樣的問題,但無法找出添加代碼以刪除引號的位置。它放在每個地方都沒有達到預期的結果。另外,我需要修改代碼以在DIR1和DIR2中查找多個配置文件。我可能會稍後再玩。雖然謝謝! – jubilare

相關問題