2011-12-05 66 views
55

關於Windows批處理文件:是否有辦法列出特定目錄及其子目錄中的所有文件(或全部特定類型),包括相對於列表中的當前(或搜索)目錄?批處理文件:列出具有相對路徑的目錄中的所有文件

例如,如果我想在當前目錄和子目錄與他們的完整路徑中的所有txt文件,我可以做

for /r . %%g in (*.txt) do echo %%g >> C:\temp\test.txt 

dir *.txt /b /s >> C:\temp\test.txt 

,我會得到這樣的

C:\test\Doc1.txt 
C:\test\subdir\Doc2.txt 
C:\test\subdir\Doc3.txt 

如果我做

for /r . %%g in (*.txt) do echo %%~nxg >> C:\temp\test.txt 

我會像

Doc1.txt 
Doc2.txt 
Doc3.txt 

但我真正想要的是:

Doc1.txt 
subdir\Doc2.txt 
subdir\Doc3.txt 

這可能嗎?

如果我的帖子太混亂了:我基本上想要「List files recursively in Linux CLI with path relative to the current directory」,只適用於Windows。

回答

22

你可以簡單地得到當前目錄的字符長度,並從絕對列表

setlocal EnableDelayedExpansion 
for /L %%n in (1 1 500) do if "!__cd__:~%%n,1!" neq "" set /a "len=%%n+1" 
setlocal DisableDelayedExpansion 
for /r . %%g in (*.log) do (
    set "absPath=%%g" 
    setlocal EnableDelayedExpansion 
    set "relPath=!absPath:~%len%!" 
    echo(!relPath! 
    endlocal 
) 
+0

'設置 「ABSPATH = %%克」'失敗如果路徑包含'!'。可以通過延遲擴展切換進行修復。 – dbenham

+3

修正'''問題,我懶惰,認爲它不會發生在某人 – jeb

9

這個答案將不包含等號(=)根路徑正常工作,將其刪除。 (感謝@dbenham指出了這一點。)


編輯:解決了該問題包含!,再次@dbenham發現路徑(謝謝!)。

替代於計算所述長度和提取的子串可以使用一種不同的方法:

  • 庫中的根路徑;

  • 清除文件路徑的根路徑。

這是我嘗試(這爲我工作):

@ECHO OFF 
SETLOCAL DisableDelayedExpansion 
SET "r=%__CD__%" 
FOR /R . %%F IN (*) DO (
    SET "p=%%F" 
    SETLOCAL EnableDelayedExpansion 
    ECHO(!p:%r%=! 
    ENDLOCAL 
) 

r變量分配與當前目錄。 除非當前目錄是磁盤驅動器的根目錄,否則它不會以\結尾,我們通過附加字符來修改它。(不再是這種情況,因爲腳本現在讀取了__CD__變量,其值總是以\結尾(謝謝@jeb!),而不是CD。)

在循環中,我們將當前文件路徑存儲到變量中。然後我們輸出變量,一路剝離根路徑。

+0

如果根路徑包含'=',這將不起作用,否則應該是好的。 – dbenham

+0

我輕而易舉地假設'='s是不允許使用名字的,而不需要首先檢查它。感謝您的注意,我將它添加到我的答案中。 –

+0

第4行應該是'IF NOT'%r:〜-1%「==」\「SET」r =%r%\「' – dbenham

4

當然,你可以寫在批遞歸算法,讓你的你在每一個嵌套的子目錄做精確控制:

@echo off 
set mypath= 
call :treeProcess 
goto :eof 

:treeProcess 
setlocal 
for %%f in (*.txt) do echo %mypath%%%f 
for /D %%d in (*) do (
    set mypath=%mypath%%%d\ 
    cd %%d 
    call :treeProcess 
    cd .. 
) 
endlocal 
exit /b 
+0

工程就像魅力! 我喜歡這種方式:-) –

+0

也是這樣,因爲在第一眼看起來似乎比延遲擴展技巧更不靈活 – grenix

30

最簡單的(但不是最快)的方式來遍歷目錄樹並列出相關的文件路徑是使用FORFILES

forfiles /s /m *.txt /c "cmd /c echo @relpath" 

的相對路徑將與領先的.\被引用爲

".\Doc1.txt" 
".\subdir\Doc2.txt" 
".\subdir\Doc3.txt" 


要刪除引號:

for /f %%A in ('forfiles /s /m *.txt /c "cmd /c echo @relpath"') do echo %%~A 


要刪除的報價和領先.\

setlocal disableDelayedExpansion 
for /f "delims=" %%A in ('forfiles /s /m *.txt /c "cmd /c echo @relpath"') do (
    set "file=%%~A" 
    setlocal enableDelayedExpansion 
    echo !file:~2! 
    endlocal 
) 

或不使用延遲擴展

for /f "tokens=1* delims=\" %%A in (
    'forfiles /s /m *.txt /c "cmd /c echo @relpath"' 
) do for %%F in (^"%%B) do echo %%~F 
+0

當我將值輸出到cmd時,如果我回顯'@ relpath >> cache.appcache' ,只有父目錄中的文件被列出。你知道可能是什麼原因造成的嗎? – rory

+0

@rory - 不是線索。如果你確定你沒有忘記使用/ S選項,那麼這聽起來值得一個新的問題。 – dbenham

+0

絕對不是,它將子目錄輸出到cmd窗口而不是txt文件。我會發佈一個新的問題,所以,感謝您的幫助 – rory

2
@echo on>out.txt 
@echo off 
setlocal enabledelayedexpansion 
set "parentfolder=%CD%" 
for /r . %%g in (*.*) do (
    set "var=%%g" 
    set var=!var:%parentfolder%=! 
    echo !var! >> out.txt 
) 
相關問題