Iteruj wszystkie pliki w katalogu za pomocą pętli „for”


352

Jak mogę iterować każdy plik w katalogu za pomocą forpętli?

A skąd mam wiedzieć, czy określony wpis jest katalogiem, czy tylko plikiem?


1
zakładając, że masz na myśli domyślną powłokę systemu Windows, zmieniłem tag twojego posta, aby uzyskać większą przejrzystość
David Schmitt,

2
Podaj również, jakiej wersji systemu Windows używasz.
jop

1
Należy to podzielić na dwa osobne pytania, ponieważ są one od siebie niezależne.
julealgon

Odpowiedzi:


492

Lista zawiera wszystkie pliki (i tylko pliki) w bieżącym katalogu:

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

Również jeśli uruchomisz to polecenie w pliku wsadowym, musisz podwoić znaki%.

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

(dzięki @agnul)


73
Jeśli nie chcesz używać tego rekurencyjnie, upewnij się, że
wyjąłeś

28
Jeśli chcesz echo tylko nazwy plików (nie pełną ścieżkę) z ich rozszerzeń w bieżącym katalogu (rekurencyjnie), można zrobić to tak: for /r %i in (*) do ( echo %~nxi ). Ten wątek może być naprawdę przydatny też: stackoverflow.com/questions/112055/... .
Sk8erPeter

2
@Vaccano tak, po Do, użyj nawiasu. Czyli (echo% i del% i). Możesz także użyć „enter” zamiast „&” dla wielu poleceń.
Jay

2
Jeśli używasz poleceń takich jak kopiuj / przenieś zamiast echa, upewnij się, że poprawnie podałeś ścieżkę. for / r %% i in (*) do echo "%% i"
Soundararajan

2
Najwyraźniej musisz użyć jednoznakowych nazw zmiennych.
Álvaro González

214

Iteruj przez ...

  • ... pliki w bieżącym katalogu: for %f in (.\*) do @echo %f
  • ... podkatalogi w bieżącym katalogu: for /D %s in (.\*) do @echo %s
  • ... pliki w bieżącym i we wszystkich podkatalogach: for /R %f in (.\*) do @echo %f
  • ... podkatalogi w bieżącym i we wszystkich podkatalogach: for /R /D %s in (.\*) do @echo %s

Niestety nie znalazłem żadnego sposobu na iterację plików i podkatalogów w tym samym czasie.

Po prostu użyj cygwina z bash, aby uzyskać znacznie większą funkcjonalność.

Poza tym: Czy zauważyłeś, że wbudowana pomoc MS Windows jest doskonałym źródłem opisów składni wiersza poleceń cmd?

Zobacz także: http://technet.microsoft.com/en-us/library/bb490890.aspx


21
%filei %subdirmoże być jedną postać długa, czyli tylko %f, %s.
Felix Dombek

1
„podkatalogi w bieżącym katalogu” nie działają.
Pojawia

78

Aby iterować po każdym pliku, zadziała pętla for:

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

W moim przypadku chciałem również zawartość pliku, nazwę itp.

Doprowadziło to do kilku problemów i pomyślałem, że mój przypadek użycia może pomóc. Oto pętla, która odczytuje informacje z każdego pliku „.txt” w katalogu i pozwala ci coś z tym zrobić (na przykład 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!"
)

* Ograniczenie: val <= %% f pobierze tylko pierwszą linię pliku.


18
Ach, przykład wieloliniowy. Dziękuję za to!
Nyerguds

@Aaron Votre Jak zakończyć pętlę?
nijogeorgep

@nijogeorgep Nie musisz „kończyć” pętli. W moim przykładzie wszystko w nawiasach (echo itp.) Będzie uruchamiane raz dla każdego pliku „* .txt” w katalogu. Myślę, że odpowiedź, której szukasz, może być lepiej wyjaśniona tutaj: stackoverflow.com/questions/1355791/…
Aaron Votre

@Aaron Votre Próbowałem uruchomić niektóre polecenia maven za pomocą skryptu, ale działało to jako nieskończona pętla, więc poprosiłem o to. Kup teraz Dodałem wyjście z mojej pętli i naprawiłem problem
nijogeorgep,

@nijogeorgep Cieszę się, że to rozgryzłeś!
Aaron Votre

57

Istnieje subtelna różnica między uruchomieniem FORz wiersza poleceń a pliku wsadowego. W pliku wsadowym musisz umieścić dwa% znaki przed każdym odwołaniem do zmiennej.

Z wiersza poleceń:

FOR %i IN (*) DO ECHO %i

Z pliku wsadowego:

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

44

Ta pętla for wyświetli wszystkie pliki w katalogu.

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

„delims =” jest przydatne do wyświetlania długich nazw plików ze spacjami ....

„/ b” pokazuje tylko nazwy, a nie daty wielkości itp.

Kilka rzeczy, które należy wiedzieć o argumencie / reż.

  • Każde użycie „/ a” wyświetlałoby wszystko, łącznie z atrybutami ukrytymi i systemowymi.
  • „/ ad” wyświetla tylko podkatalogi, w tym ukryte i systemowe.
  • Argument „/ ad” eliminuje zawartość z atrybutem „D”.
  • „/ adhs” pokaże wszystko, ale wpisy z atrybutem „D'irectory”, „H'idden” S'ystem.

Jeśli używasz tego w wierszu poleceń, usuń „%”.

Mam nadzieję że to pomoże.


10

% 1 odnosi się do pierwszego przekazanego argumentu i nie można go użyć w iteratorze.

Spróbuj tego:

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

Masz rację. Próbowałem w trybie natychmiastowym sprawdzić składnię FOR i wkleiłem wiersz prosto do odpowiedzi, zapominając o parametrach :-)
Axeman


4

Aby iterować wszystkie pliki i foldery, których możesz użyć

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

Aby przejść do wszystkich folderów nie tylko z plikami, możesz użyć

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

Gdzie /sda wszystkie wyniki w drzewie katalogów na nieograniczonej głębokości. Możesz pominąć, /sjeśli chcesz iterować zawartość tego folderu, a nie jego podfolderu

Wdrażanie wyszukiwania w iteracji

Aby wykonać iterację według określonych nazwanych plików i folderów , możesz wyszukać nazwę i iterować za pomocą pętli for

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

Aby wykonać iterację według określonych nazwanych folderów / katalogów, a nie plików , użyj /ADtego samego polecenia

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

4

Miałem problem z uzyskaniem odpowiedzi JOP z bezwzględną ścieżką, dopóki nie znalazłem tej referencji: https://ss64.com/nt/for_r.html

Poniższy przykład zapętla wszystkie pliki w katalogu podanym przez ścieżkę bezwzględną.

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

3

Poniższy kod tworzy plik o nazwie „AllFilesInCurrentDirectorylist.txt” w bieżącym katalogu, który zawiera listę wszystkich plików (tylko pliki) w bieżącym katalogu. Sprawdź to

dir /b /a-d > AllFilesInCurrentDirectorylist.txt

3

Może również użyć polecenia forfiles :

forfiles /s 

a także sprawdź, czy jest to katalog

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

@isdir==truemusi być@isdir==TRUE
psyklopz

2

Użyłbym vbscript (Windows Scripting Host), ponieważ wsadowo jestem pewien, że nie możesz powiedzieć, że nazwa jest plikiem lub katalogiem.

W VBS może to być coś takiego:

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

Sprawdź FileSystemObject na MSDN .


Użyłbym do tego Perla. Niestety to nie zależy ode mnie.
Vhaerun

Jakaś stara aplikacja? Smutne rzeczy
Biri

Idiotyczny programista zobaczył pliki wsadowe i pomyślał, że są lekarstwem na wszystkie nasze problemy.
Vhaerun

1
@Vhaerun Jedną z zalet hosta skryptów systemu Windows (WSH) w stosunku do Perla jest to, że WSH jest wstępnie zainstalowany ze wszystkimi wersjami systemu Windows, podczas gdy Perl musiałby być instalowany osobno, co może, ale nie musi być wykonalną opcją we wszystkich przypadkach.
Parampreet Dhatt

2

Używam polecenia xcopy z opcją / L, aby uzyskać nazwy plików. Więc jeśli chcesz uzyskać katalog lub wszystkie pliki w podkatalogu, możesz zrobić coś takiego:

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

Po prostu używam c: \ jako miejsca docelowego, ponieważ zawsze istnieje w systemach Windows i nie kopiuje, więc nie ma znaczenia. jeśli chcesz też podkatalogów, po prostu użyj opcji / s na końcu. Możesz także użyć innych przełączników xcopy, jeśli potrzebujesz ich z innych powodów.


2

Spróbuj tego, aby sprawdzić, czy plik jest katalogiem:

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

To tylko powie ci, czy plik NIE jest katalogiem, co będzie również prawdą, jeśli plik nie istnieje, więc najpierw sprawdź, czy jest to konieczne. Kreski (^) służą do zmiany symboli przekierowania, a dane wyjściowe listy plików są przekierowywane do NUL, aby zapobiec ich wyświetleniu, podczas gdy dane wyjściowe błędów list DIR są przekierowywane do danych wyjściowych, dzięki czemu można przetestować komunikat DIR „Nie znaleziono pliku „.


2

Spróbuj tego:

::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

zlicza pliki .msi i .exe w twoim katalogu (i podkatalogu). Czyni to także różnicę między folderami i plikami jako plikami wykonywalnymi.

Po prostu dodaj rozszerzenie (.pptx .docx ..), jeśli chcesz filtrować inne pliki w pętli


1

W moim przypadku musiałem usunąć wszystkie pliki i foldery poniżej folderu tymczasowego. Tak właśnie skończyłem. Musiałem uruchomić dwie pętle, jedną dla plików i jedną dla folderów. Jeśli pliki lub foldery mają spacje w swoich nazwach, musisz użyć „”

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

Oto moje komentarze z komentarzami w kodzie.

Po prostu poprawiam umiejętności biatch, więc wybaczam rażące błędy.

Próbowałem napisać rozwiązanie typu „wszystko w jednym” najlepiej jak potrafię, z niewielką modyfikacją tam, gdzie wymaga tego użytkownik.

Kilka ważnych uwag: Po prostu zmień zmienną recursivena, FALSEjeśli chcesz przetwarzać tylko pliki i foldery katalogów głównych. W przeciwnym razie przejdzie przez wszystkie foldery i pliki.

Zapraszamy 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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.