ทำซ้ำไฟล์ทั้งหมดในไดเรกทอรีโดยใช้ลูป 'for'


352

ฉันจะวนซ้ำแต่ละไฟล์ในไดเรกทอรีโดยใช้การforวนซ้ำได้อย่างไร

และฉันจะบอกได้อย่างไรว่ารายการบางรายการเป็นไดเรกทอรีหรือถ้าเป็นเพียงไฟล์?


1
สมมติว่าคุณหมายถึงการเริ่มต้นหน้าต่างเปลือกผมได้ติดแท็กโพสต์ของคุณนิด ๆ หน่อย ๆ ความชัดเจนมากขึ้น
เดวิดมิต

2
โปรดระบุรุ่นของ Windows ที่คุณใช้ด้วย
jop

1
คำถามนี้ควรแบ่งออกเป็นสองคำถามแยกกันเพราะเป็นอิสระจากกัน
julealgon

คำตอบ:


492

รายการนี้แสดงไฟล์ทั้งหมด (และเฉพาะไฟล์) ในไดเรกทอรีปัจจุบัน:

for /r %i in (*) do echo %i

นอกจากนี้หากคุณเรียกใช้คำสั่งนั้นในไฟล์แบตช์คุณต้องเพิ่มเครื่องหมาย%

for /r %%i in (*) do echo %%i

(ขอบคุณ @agnul)


73
หากคุณไม่ต้องการใช้งานแบบวนซ้ำตรวจสอบให้แน่ใจว่าคุณได้ออก / r
jocull

28
หากคุณต้องการที่จะสะท้อนเพียงชื่อไฟล์ (ไม่ใช่เส้นทางแบบเต็ม) ที่มีส่วนขยายของพวกเขาในไดเรกทอรีปัจจุบัน (ซ้ำ) for /r %i in (*) do ( echo %~nxi )คุณสามารถทำมันได้เช่นนี้ หัวข้อนี้จะมีประโยชน์จริงๆเกินไป: stackoverflow.com/questions/112055/...
Sk8erPeter

2
@Vaccano ใช่หลังจากใช้ Do ให้ใช้เครื่องหมายวงเล็บ นั่นคือ (echo% i & del% i) คุณยังสามารถใช้ "ป้อน" แทน "&" สำหรับหลายคำสั่ง
Jay

2
หากคุณใช้คำสั่งเช่นคัดลอก / ย้ายแทนที่จะเป็นเสียงก้องตรวจสอบให้แน่ใจว่าคุณอ้างเส้นทางอย่างถูกต้อง สำหรับ / r %% i ใน (*) ทำเสียงสะท้อน "%% i"
Soundararajan

2
คุณต้องใช้ชื่อตัวแปรตัวอักษรเดียว
ÁlvaroGonzález

214

ทำซ้ำผ่าน ...

  • ... ไฟล์ใน dir ปัจจุบัน: for %f in (.\*) do @echo %f
  • ... subdirs ใน dir ปัจจุบัน: for /D %s in (.\*) do @echo %s
  • ... ไฟล์ในส่วนย่อยปัจจุบันและทั้งหมด: for /R %f in (.\*) do @echo %f
  • ... ตำบลในปัจจุบันและตำบลทั้งหมด: for /R /D %s in (.\*) do @echo %s

น่าเสียดายที่ฉันไม่พบวิธีที่จะวนซ้ำไฟล์และโฟลเดอร์ย่อยในเวลาเดียวกัน

เพียงใช้cygwinพร้อมกับ bash เพื่อการใช้งานที่มากขึ้น

นอกเหนือจากนี้: คุณสังเกตเห็นหรือไม่ว่าความช่วยเหลือ buildin ของ MS Windows เป็นทรัพยากรที่ดีเยี่ยมสำหรับคำอธิบายของไวยากรณ์บรรทัดคำสั่งของ cmd?

ดูที่นี่: http://technet.microsoft.com/en-us/library/bb490890.aspx


21
%fileและ%subdirสามารถเป็นตัวละครตัวหนึ่งยาวเช่น,%f %s
Felix Dombek

1
'subdirs ใน dir ปัจจุบัน' ไม่ทำงาน ฉันได้รับข้อผิดพลาด: s ไม่คาดคิดในขณะนี้
Migrate2Lazarus ดูโปรไฟล์ของฉัน

78

หากต้องการวนซ้ำแต่ละไฟล์ a for loop จะทำงาน:

for %%f in (directory\path\*) do ( something_here )

ในกรณีของฉันฉันต้องการเนื้อหาไฟล์ชื่อและอื่น ๆ

นำไปสู่ปัญหาเล็กน้อยและฉันคิดว่ากรณีการใช้งานของฉันอาจช่วยได้ นี่คือลูปที่อ่านข้อมูลจากไฟล์ '.txt' แต่ละไฟล์ในไดเรกทอรีและอนุญาตให้คุณทำบางสิ่งกับมัน (เช่น setx)

@ECHO OFF
setlocal enabledelayedexpansion
for %%f in (directory\path\*.txt) do (
  set /p val=<%%f
  echo "fullname: %%f"
  echo "name: %%~nf"
  echo "contents: !val!"
)

* ข้อ จำกัด : val <= %% f จะได้รับบรรทัดแรกของไฟล์เท่านั้น


18
อาตัวอย่างหลายบรรทัด ขอบคุณสำหรับสิ่งนั้น!
Nyerguds

@Aaron Votre วิธีจบลูป
nijogeorgep

@nijogeorgep คุณไม่ต้อง "จบ" การวนซ้ำ ในตัวอย่างของฉันทุกอย่างที่อยู่ในวงเล็บ (echo ฯลฯ ) จะถูกเรียกใช้ครั้งเดียวสำหรับไฟล์ '* .txt' แต่ละไฟล์ในไดเรกทอรี ฉันคิดว่าคำตอบที่คุณกำลังมองหาอาจอธิบายได้ดีกว่าที่นี่: stackoverflow.com/questions/1355791//
Aaron Votre

@Aaron Votre ฉันพยายามเรียกใช้คำสั่ง maven โดยใช้สคริปต์ แต่มันทำงานเป็นลูปไม่สิ้นสุดดังนั้นฉันจึงถาม ซื้อตอนนี้ฉันเพิ่มทางออกให้กับลูปของฉันและแก้ไขปัญหาของฉัน
nijogeorgep

@nijogeorgep ดีใจที่คุณคิดออก!
Aaron Votre

57

มีความแตกต่างเล็กน้อยระหว่างการเรียกใช้FORจากบรรทัดคำสั่งและจากชุดไฟล์ ในไฟล์แบตช์คุณต้องใส่%อักขระสองตัวไว้หน้าการอ้างอิงตัวแปรแต่ละตัว

จากบรรทัดคำสั่ง:

FOR %i IN (*) DO ECHO %i

จากแบตช์ไฟล์:

FOR %%i IN (*) DO ECHO %%i

44

for-loop นี้จะแสดงรายการไฟล์ทั้งหมดในไดเรกทอรี

pushd somedir
for /f "delims=" %%f in ('dir /b /a-d-h-s') do echo %%f
popd

"delims =" มีประโยชน์ในการแสดงชื่อไฟล์แบบยาวที่มีช่องว่างในนั้น ...

'/ b "แสดงเฉพาะชื่อไม่ใช่วันที่ขนาด ฯลฯ

บางสิ่งที่ต้องรู้เกี่ยวกับข้อโต้แย้งของ dir

  • การใช้ "/ a" จะแสดงรายการทุกอย่างรวมถึงแอตทริบิวต์ที่ซ่อนอยู่และระบบ
  • "/ ad" จะแสดงเฉพาะไดเรกทอรีย่อยรวมถึงรายการที่ซ่อนอยู่และรายการระบบ
  • อาร์กิวเมนต์ "/ ad" กำจัดเนื้อหาด้วยแอตทริบิวต์ 'D'irectory
  • "/ adhs" จะแสดงทุกอย่าง แต่รายการที่มีแอตทริบิวต์ 'D'irectory,' H'idden 'S'ystem

หากคุณใช้สิ่งนี้กับ commandline ให้ลบ "%"

หวังว่านี่จะช่วยได้


10

% 1 อ้างถึงอาร์กิวเมนต์แรกที่ส่งผ่านและไม่สามารถใช้ในตัววนซ้ำได้

ลองสิ่งนี้:

@echo off
for %%i in (*.*) do echo %%i

คุณถูก. ฉันได้พยายามในโหมดทันทีเพื่อตรวจสอบไวยากรณ์สำหรับและวางสายตรงเข้าไปในคำตอบที่ลืมเกี่ยวกับพารามิเตอร์ :-)
Axeman

5
for %1 in (*.*) do echo %1

ลองใช้ "ความช่วยเหลือเพื่อ" ใน cmd สำหรับคำแนะนำแบบเต็ม

นี่คือคำแนะนำสำหรับคำสั่ง XP http://www.ss64.com/nt/


4

ในการวนซ้ำไฟล์และโฟลเดอร์ทั้งหมดที่คุณสามารถใช้ได้

for /F "delims=" %%a in ('dir /b /s') do echo %%a

ในการวนซ้ำในโฟลเดอร์ทั้งหมดไม่ได้มีเฉพาะไฟล์คุณสามารถใช้

for /F "delims=" %%a in ('dir /a:d /b /s') do echo %%a

ไหน/sจะให้ผลลัพธ์ทั้งหมดตลอดทั้งต้นไม้ไดเรกทอรีในเชิงลึกไม่ จำกัด คุณสามารถข้ามได้/sหากคุณต้องการวนซ้ำเนื้อหาของโฟลเดอร์นั้นไม่ใช่โฟลเดอร์ย่อย

การนำการค้นหาไปใช้ในการทำซ้ำ

ในการวนซ้ำไฟล์และโฟลเดอร์ที่มีชื่อเฉพาะคุณสามารถค้นหาชื่อและวนซ้ำโดยใช้ลูป

for /F "delims=" %%a in ('dir "file or folder name" /b /s') do echo %%a

หากต้องการวนซ้ำโฟลเดอร์ / ไดเรกทอรีที่มีชื่อเฉพาะและไม่ใช่ไฟล์ให้ใช้/ADคำสั่งเดียวกัน

for /F "delims=" %%a in ('dir "folder name" /b /AD /s') do echo %%a

4

ฉันมีปัญหาในการรับคำตอบของ jop เพื่อทำงานกับพา ธ สัมบูรณ์จนกว่าฉันจะพบข้อมูลอ้างอิงนี้: https://ss64.com/nt/for_r.html

ตัวอย่างต่อไปนี้วนซ้ำไฟล์ทั้งหมดในไดเรกทอรีที่กำหนดโดยพา ธ สัมบูรณ์

For /R C:\absoulte\path\ %%G IN (*.*) do (
  Echo %%G
)

3

รหัสต่อไปนี้สร้างไฟล์ชื่อ"AllFilesInCurrentDirectorylist.txt"ในไดเรกทอรีปัจจุบันซึ่งมีรายการไฟล์ทั้งหมด (เฉพาะไฟล์) ในไดเรกทอรีปัจจุบัน ลองดูสิ

dir /b /a-d > AllFilesInCurrentDirectorylist.txt

3

มันยังสามารถใช้คำสั่งforfiles :

forfiles /s 

และตรวจสอบว่าเป็นไดเรกทอรีหรือไม่

forfiles /p c:\ /s /m *.* /c "cmd /c if @isdir==true echo @file is a directory"

@isdir==trueต้องเป็น@isdir==TRUE
psyklopz

2

ฉันจะใช้ vbscript (Windows Scripting Host) เพราะในชุดฉันแน่ใจว่าคุณไม่สามารถบอกได้ว่าชื่อเป็นไฟล์หรือไดเรกทอรี

ใน vbs อาจเป็นดังนี้:

Dim fileSystemObject
Set fileSystemObject = CreateObject("Scripting.FileSystemObject")

Dim mainFolder
Set mainFolder = fileSystemObject.GetFolder(myFolder)

Dim files
Set files = mainFolder.Files

For Each file in files
...
Next

Dim subFolders
Set subFolders = mainFolder.SubFolders

For Each folder in subFolders
...
Next

ตรวจสอบFileSystemObject ใน MSDN


ฉันจะใช้ Perl เพื่อทำสิ่งนี้ น่าเสียดายที่มันไม่ได้ขึ้นอยู่กับฉัน
Vhaerun

แอปพลิเคชันเก่า ๆ สิ่งที่น่าเศร้า
Biri

นักพัฒนาที่งี่เง่าเห็นไฟล์แบตช์และคิดว่าพวกเขาแก้ปัญหาทั้งหมดของเราได้แล้ว
Vhaerun

1
@Vhaerun ข้อดีอย่างหนึ่งของ Windows Script Host (WSH) บน Perl ก็คือ WSH นั้นติดตั้งมาพร้อมกับ Windows ทุกรุ่นในขณะที่ Perl จะต้องติดตั้งแยกต่างหากซึ่งอาจเป็นตัวเลือกที่เหมาะสมหรือเป็นไปไม่ได้ในทุกกรณี
Parampreet Dhatt

2

ฉันใช้คำสั่ง xcopy พร้อมกับตัวเลือก / L เพื่อรับชื่อไฟล์ ดังนั้นหากคุณต้องการได้รับไดเรกทอรีหรือไฟล์ทั้งหมดในไดเรกทอรีย่อยคุณสามารถทำสิ่งนี้:

for /f "delims=" %%a IN ('xcopy "D:\*.pdf" c:\ /l') do echo %%a

ฉันเพิ่งใช้ c: \ เป็นปลายทางเพราะมันมีอยู่เสมอในระบบ windows และมันไม่ได้คัดลอกดังนั้นจึงไม่สำคัญ หากคุณต้องการไดเรกทอรีย่อยก็ใช้ตัวเลือก / s ที่สิ้นสุด คุณสามารถใช้สวิตช์อื่นของ xcopy ได้หากคุณต้องการเหตุผลอื่น


2

ลองใช้วิธีนี้เพื่อทดสอบว่าไฟล์เป็นไดเรกทอรีหรือไม่:

FOR /F "delims=" %I IN ('DIR /B /AD "filename" 2^>^&1 ^>NUL') DO IF "%I" == "File Not Found" ECHO Not a directory

สิ่งนี้จะบอกคุณว่าไฟล์ไม่ใช่ไดเรกทอรีหรือไม่ซึ่งจะเป็นจริงหากไฟล์ไม่มีอยู่ดังนั้นโปรดตรวจสอบให้แน่ใจก่อนว่าคุณจำเป็นต้องใช้หรือไม่ carets (^) ใช้เพื่อหลบหนีสัญลักษณ์การเปลี่ยนเส้นทางและเอาต์พุตรายการไฟล์ถูกเปลี่ยนเส้นทางไปยัง NUL เพื่อป้องกันไม่ให้แสดงในขณะที่เอาต์พุตข้อผิดพลาดของรายการ DIR ถูกเปลี่ยนเส้นทางไปยังเอาต์พุตเพื่อให้คุณสามารถทดสอบกับข้อความของ DIR "File Not Found "


2

ลองนี้:

::Example directory
set SetupDir=C:\Users

::Loop in the folder with "/r" to search in recursive folders, %%f being a loop ::variable 
for /r "%SetupDir%" %%f in (*.msi *.exe) do set /a counter+=1

echo there are %counter% files in your folder

มันนับไฟล์. msi และ. exe ในไดเรกทอรีของคุณ (และในไดเรกทอรีย่อย) ดังนั้นมันยังสร้างความแตกต่างระหว่างโฟลเดอร์และไฟล์ต่างๆ

เพียงเพิ่มนามสกุล (.pptx .docx .. ) หากคุณต้องการกรองไฟล์อื่น ๆ ในลูป


1

ในกรณีของฉันฉันต้องลบไฟล์และโฟลเดอร์ทั้งหมดภายใต้โฟลเดอร์ temp ดังนั้นนี่คือวิธีที่ฉันลงเอยทำ ฉันต้องเรียกใช้สองลูปหนึ่งสำหรับไฟล์และอีกหนึ่งสำหรับโฟลเดอร์ หากไฟล์หรือโฟลเดอร์มีช่องว่างในชื่อพวกเขาคุณต้องใช้ ""

cd %USERPROFILE%\AppData\Local\Temp\
rem files only
for /r %%a in (*) do (
echo deleting file "%%a" ...
if exist "%%a" del /s /q "%%a"
)
rem folders only
for /D %%a in (*) do (
echo deleting folder "%%a" ...
if exist "%%a" rmdir /s /q "%%a"
)

1

นี่ฉันไปด้วยความคิดเห็นในรหัส

ฉันแค่แปรงฟันด้วยทักษะ biatch ดังนั้นให้อภัยข้อผิดพลาดที่เห็นได้ชัด

ฉันพยายามเขียนโซลูชันทั้งหมดในที่เดียวให้ดีที่สุดด้วยการปรับเปลี่ยนเล็กน้อยซึ่งผู้ใช้ต้องการ

หมายเหตุสำคัญบางประการ:เพียงเปลี่ยนตัวแปรrecursiveเป็นFALSEหากคุณต้องการให้ไฟล์และโฟลเดอร์ไดเรกทอรีรากดำเนินการ มิฉะนั้นจะผ่านโฟลเดอร์และไฟล์ทั้งหมด

ยินดีต้อนรับมากที่สุด C&C ...

@echo off
title %~nx0
chcp 65001 >NUL
set "dir=c:\users\%username%\desktop"
::
:: Recursive Loop routine - First Written by Ste on - 2020.01.24 - Rev 1
::
setlocal EnableDelayedExpansion
rem THIS IS A RECURSIVE SOLUTION [ALBEIT IF YOU CHANGE THE RECURSIVE TO FALSE, NO]
rem By removing the /s switch from the first loop if you want to loop through
rem the base folder only.
set recursive=TRUE
if %recursive% equ TRUE ( set recursive=/s ) else ( set recursive= )
endlocal & set recursive=%recursive%
cd /d %dir%
echo Directory %cd%
for %%F in ("*") do (echo    → %%F)                                 %= Loop through the current directory. =%
for /f "delims==" %%D in ('dir "%dir%" /ad /b %recursive%') do (    %= Loop through the sub-directories only if the recursive variable is TRUE. =%
  echo Directory %%D
  echo %recursive% | find "/s" >NUL 2>NUL && (
    pushd %%D
    cd /d %%D
    for /f "delims==" %%F in ('dir "*" /b') do (                      %= Then loop through each pushd' folder and work on the files and folders =%
      echo %%~aF | find /v "d" >NUL 2>NUL && (                        %= This will weed out the directories by checking their attributes for the lack of 'd' with the /v switch therefore you can now work on the files only. =%
      rem You can do stuff to your files here.
      rem Below are some examples of the info you can get by expanding the %%F variable.
      rem Uncomment one at a time to see the results.
      echo    → %%~F           &rem expands %%F removing any surrounding quotes (")
      rem echo    → %%~dF          &rem expands %%F to a drive letter only
      rem echo    → %%~fF          &rem expands %%F to a fully qualified path name
      rem echo    → %%~pF          &rem expands %%A to a path only
      rem echo    → %%~nF          &rem expands %%F to a file name only
      rem echo    → %%~xF          &rem expands %%F to a file extension only
      rem echo    → %%~sF          &rem expanded path contains short names only
      rem echo    → %%~aF          &rem expands %%F to file attributes of file
      rem echo    → %%~tF          &rem expands %%F to date/time of file
      rem echo    → %%~zF          &rem expands %%F to size of file
      rem echo    → %%~dpF         &rem expands %%F to a drive letter and path only
      rem echo    → %%~nxF         &rem expands %%F to a file name and extension only
      rem echo    → %%~fsF         &rem expands %%F to a full path name with short names only
      rem echo    → %%~dp$dir:F    &rem searches the directories listed in the 'dir' environment variable and expands %%F to the fully qualified name of the first one found. If the environment variable name is not defined or the file is not found by the search, then this modifier expands to the empty string
      rem echo    → %%~ftzaF       &rem expands %%F to a DIR like output line
      )
      )
    popd
    )
  )
echo/ & pause & cls
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.