2011-12-05 32 views
55

Liên quan đến tập tin Windows Batch: Có cách nào để liệt kê tất cả các tệp (hoặc tất cả một loại cụ thể) trong một thư mục nhất định và thư mục con của nó hay không thư mục hiện tại (hoặc tìm kiếm) trong danh sách?Batch Files: Liệt kê tất cả các tập tin trong một thư mục có đường dẫn tương đối

Ví dụ, nếu tôi muốn tất cả các file txt trong thư mục hiện hành và thư mục con với đường dẫn đầy đủ của họ, tôi có thể làm

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

hoặc

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

và tôi sẽ nhận được một cái gì đó giống như

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

Nếu tôi làm

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

tôi sẽ nhận được một cái gì đó giống như

Doc1.txt 
Doc2.txt 
Doc3.txt 

Nhưng những gì tôi thực sự muốn là:

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

Có thể?

Nếu bài đăng của tôi quá khó hiểu: về cơ bản tôi muốn "List files recursively in Linux CLI with path relative to the current directory", chỉ dành cho Windows.

Trả lời

22

Bạn chỉ có thể có được độ dài đặc trưng của thư mục hiện hành, và loại bỏ chúng khỏi danh sách tuyệt đối của bạn

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

'thiết lập "absPath = %% g" 'thất bại nếu đường dẫn chứa'! '. Có thể được cố định với việc mở rộng chậm trễ. – dbenham

+3

Cố định vấn đề '!', Tôi đã lười biếng, nghĩ rằng nó sẽ không xảy ra với ai đó – jeb

9

Câu trả lời này sẽ không hoạt động với các đường dẫn thư mục gốc chứa dấu bằng (=). (Cảm ơn @dbenham đã chỉ ra rằng.)


EDITED: Cố định vấn đề với đường dẫn chứa !, một lần nữa phát hiện bởi @dbenham (nhờ!).

Ngoài ra để tính toán độ dài và giải nén chuỗi con bạn có thể sử dụng một cách tiếp cận khác nhau:

  • cửa hàng đường dẫn gốc;

  • xóa đường dẫn gốc khỏi đường dẫn tệp.

Đây là nỗ lực của tôi (mà làm việc cho tôi):

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

Biến r được gán với thư mục hiện hành. Trừ khi thư mục hiện tại là thư mục gốc của ổ đĩa, nó sẽ không kết thúc bằng \, mà chúng tôi sửa đổi bằng cách chắp thêm ký tự.(Không còn trường hợp nào, vì tập lệnh bây giờ đọc biến số __CD__, có giá trị luôn kết thúc bằng \ (nhờ @jeb!), thay vì CD.)

Trong vòng lặp, chúng tôi lưu trữ đường dẫn tệp hiện tại vào một biến. Sau đó, chúng tôi xuất các biến, tước đường dẫn gốc trên đường đi.

+0

Điều này sẽ không hoạt động nếu đường dẫn gốc chứa '=', nhưng nếu không thì tốt. – dbenham

+0

Tôi nhẹ nhàng coi là '=' s không được phép trong các tên, mà không gặp khó khăn khi kiểm tra đầu tiên. Cảm ơn bạn đã lưu ý, tôi sẽ thêm nó vào câu trả lời của tôi. –

+0

Dòng 4 phải là 'NẾU KHÔNG"% r: ~ -1% "==" \ "SET" r =% r% \ "' – dbenham

4

Tất nhiên, bạn có thể viết một thuật toán đệ quy trong hàng loạt cung cấp cho bạn kiểm soát chính xác những gì bạn làm trong mỗi thư mục con lồng nhau:

@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

Hoạt động như sự quyến rũ! Tôi thích cách tiếp cận này :-) –

+0

như thế này cũng giống như cái nhìn đầu tiên có vẻ ít bận tâm hơn các thủ thuật mở rộng bị trì hoãn – grenix

30

Cách đơn giản nhất (nhưng không phải là nhanh nhất) cách để lặp một cây thư mục và liệt kê các đường dẫn tệp tương đối là sử dụng FORFILES.

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

Các đường dẫn tương đối sẽ được trích dẫn với một .\ hàng đầu như trong

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


dấu ngoặc kép Để loại bỏ:

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


Để loại bỏ dấu ngoặc kép và hàng đầu .\:

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 
) 

hoặc không sử dụng mở rộng chậm

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

giải pháp của bạn hoạt động khi tôi xuất các giá trị thành cmd nhưng nếu tôi echo ´ @ relpath >> cache.appcache´ , chỉ các tệp trong thư mục chính mới được liệt kê. Bạn có biết điều gì có thể gây ra điều đó không? – rory

+0

@rory - Không phải là đầu mối.Nếu bạn chắc chắn bạn đã không quên sử dụng tùy chọn/S, thì âm thanh đó xứng đáng với một câu hỏi mới. – dbenham

+0

chắc chắn không, nó kết quả đầu ra các thư mục phụ để cửa sổ cmd nhưng không phải là tập tin txt. Tôi sẽ đăng một câu hỏi mới, nhờ sự giúp đỡ của bạn – 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 
) 
Các vấn đề liên quan