2011-04-09 25 views
1

我的命令行參數爲我的批處理腳本提供了一個文件名和一個文件夾的列表。對於每個文件名,我需要打印文件所在文件夾的所有子文件夾(該文件的路徑)。子文件夾名稱應按文件大小的降序排列(文件在不同子文件夾中可以有不同的大小)。查找文件並在Windows批處理文件中按大小排序

我迄今所做的這一點,但它不工作:

::verify if the first parameter is the directory 

@echo off 
REM check the numbers of parameters 
if "%2"=="" goto err1 
REM check: is first parameter a directory? 
if NOT EXIST %1\NUL goto err2 
set d=%1 
shift 
REM iterate the rest of the parameters 


for %%i in %dir do (
find %dir /name %i > temp 

if EXIST du /b temp | cut /f 1 goto err3 
myvar=TYPE temp 
echo "file " %i "is in: " 

for %%j in %myvar do 
echo %j 

echo after sort 
du /b %myvar | sort /nr  
) 

:err1 
echo Two parameters are necessary 
goto end 

:err2 
echo First parameter must be a directory. 
goto end 

:err3 
echo file does not exist. 
goto end 

:end 
+0

我已經做了一些改進,雖然我不能作出這樣找到的文件路徑的腳本。 – 2011-04-10 18:23:29

+1

不要創建幾個平等的問題!如果需要 - 只需編輯問題。 – abatishchev 2011-04-10 18:30:45

+0

你有沒有必要在DOS下做到這一點?如果PowerShell可用,則可能會發現在Powershell中編寫此代碼更容易,該代碼具有優良的排序和篩選功能。你不需要一個PowerShell控制檯 - 你可以直接從DOS直接運行PowerShell命令,只需調用powershell.exe並將命令或路徑傳遞給.ps1腳本 – 2011-04-19 12:37:39

回答

6

我不感到內疚,現在回答這個問題功課的學期早已過去。 Print folders and files recursively using Windows Batch是一個封閉的重複問題,討論分配。

我最初的解決方案非常簡單。有幾個技巧可以確保它能正確處理其中包含特殊字符的路徑,但不會太花哨。唯一的另一個技巧是用空格填充文件大小,以便SORT正常工作。

就像在原來的問題中,第一個參數應該是一個文件夾路徑(。\工作得很好),並且隨後的參數表示文件名(通配符都可以)。

@echo off 
setlocal disableDelayedExpansion 
set tempfile="%temp%\_mysort%random%.txt" 

set "root=" 
for %%F in (%*) do (
    if not defined root (
    pushd %%F || exit /b 
    set root=1 
) else (
    echo(
    echo %%~nxF 
    echo -------------------------------------------- 
    (
     @echo off 
     for /f "eol=: delims=" %%A in ('dir /s /b "%%~nxF"') do (
     set "mypath=%%~dpA" 
     set "size=   %%~zA" 
     setlocal enableDelayedExpansion 
     set "size=!size:~-12!" 
     echo !size! !mypath! 
     endlocal 
    ) 
    ) >%tempfile% 
     sort /r %tempfile% 
) 
) 
if exist %tempfile% del %tempfile% 
if defined root popd 

我希望避免創建一個臨時文件,通過直接替換重定向和隨後的排序管道進行排序。但這不起作用。 (請參閱我的相關問題:Why does delayed expansion fail when inside a piped block of code?

我的第一個解決方案運行良好,除了根據提供的輸入有可能產生重複輸出。我決定編寫一個能夠清除重複文件報告的版本。

基本前提很簡單 - 將所有輸出保存爲一個臨時文件,並將文件名添加到已排序字符串的前面。然後,我需要遍歷結果並僅在文件和/或路徑更改時打印信息。

最後一個循環是最棘手的部分,因爲文件名可以包含像!^&%特殊字符可能導致問題取決於使用何種類型的擴展。我需要在循環中設置和比較變量,這通常需要延遲擴展。但是,當找到!時,延遲擴展會導致FOR變量擴展出現問題。我可以通過調用外部循環來避免延遲擴展,但是隨後FOR變量變得不可用。我可以將變量作爲參數傳遞給CALLed例程而不會延遲擴展,但是隨後我遇到了%^&的問題。我可以用SETLOCAL/ENDLOCAL玩遊戲,但是我需要擔心通過ENDLOCAL屏障傳遞值,這需要一個相當複雜的轉義過程。問題成爲一個巨大的惡性循環。

另一個自我強加的約束是我不想用引號括起文件和路徑輸出,這意味着我必須使用延遲擴展,FOR變量或轉義值。

我發現了一個有趣的解決方案,它利用了FOR變量的奇特功能。

通常,FOR變量的範圍嚴格限於循環內。如果您在循環外調用,則FOR變量值不再可用。但是,如果您在被調用的過程中發出FOR語句 - 調用者FOR變量將再次變爲可見!問題解決!

@echo off 
setlocal disableDelayedExpansion 
set tempfile="%temp%\_mysort%random%.txt" 
if exist %tempfile% del %tempfile% 

set "root=" 
(
    for %%F in (%*) do (
    if not defined root (
     pushd %%F || exit /b 
     set root=1 
    ) else (
     set "file=%%~nxF" 
     for /f "eol=: delims=" %%A in ('dir /s /b "%%~nxF"') do (
     set "mypath=%%~dpA" 
     set "size=   %%~zA" 
     setlocal enableDelayedExpansion 
     set "size=!size:~-12!" 
     echo(!file!/!size!/!mypath! 
     endlocal 
    ) 
    ) 
) 
)>%tempfile% 

set "file=" 
set "mypath=" 
for /f "tokens=1-3 eol=/ delims=/" %%A in ('sort /r %tempfile%') do call :proc 

if exist %tempfile% del %tempfile% 
if defined root popd 
exit /b 

:proc 
    for %%Z in (1) do (
    if "%file%" neq "%%A" (
     set "file=%%A" 
     set "mypath=" 
     echo(
     echo %%A 
     echo -------------------------------------------- 
    ) 
) 
    for %%Z in (1) do (
    if "%mypath%" neq "%%C" (
     set "mypath=%%C" 
     echo %%B %%C 
    ) 
) 
exit /b 
相關問題