Iterar todos os arquivos em um diretório usando um loop 'for'

352

Como posso iterar sobre cada arquivo em um diretório usando um forloop?

E como eu poderia saber se uma determinada entrada é um diretório ou se é apenas um arquivo?

Vhaerun
fonte
11
supondo que você significou o shell do Windows padrão, eu retagged seu post para um pouco de mais clareza
David Schmitt
2
Especifique também qual versão do Windows você está usando.
jop
11
Isso deve ser dividido em duas perguntas separadas, pois são independentes uma da outra.
julealgon

Respostas:

492

Isso lista todos os arquivos (e apenas os arquivos) no diretório atual:

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

Além disso, se você executar esse comando em um arquivo em lotes, precisará dobrar os sinais de%.

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

(obrigado @agnul)

piada
fonte
73
Se você não quiser usar isso recursivamente, certifique-se de remover o / r
jocull
28
Se você gostaria de fazer eco única os nomes de arquivos (não o caminho completo), com suas extensões no diretório atual (de forma recursiva), você pode fazê-lo como este: for /r %i in (*) do ( echo %~nxi ). Esse encadeamento também pode ser realmente útil: stackoverflow.com/questions/112055/… .
precisa saber é o seguinte
2
@ Vulcano sim, depois do Do, use parênteses. Ou seja, (eco% i & del% i). Você também pode usar "enter" em vez de "&" para vários comandos.
Jay em
2
Se você estiver usando comandos como copiar / mover em vez de eco, certifique-se de citar o caminho corretamente. para / r %% i em (*) echo "%% i"
Soundararajan 24/10
2
Aparentemente, você precisa usar nomes de variáveis ​​com uma única letra.
Álvaro González
214

Iterar através de ...

  • ... arquivos no diretório atual: for %f in (.\*) do @echo %f
  • ... subdiretórios no dir atual: for /D %s in (.\*) do @echo %s
  • ... arquivos atuais e todos os subdiretórios: for /R %f in (.\*) do @echo %f
  • ... subdiretórios em atual e todos os subdiretórios: for /R /D %s in (.\*) do @echo %s

Infelizmente, não encontrei nenhuma maneira de iterar arquivos e subdiretórios ao mesmo tempo.

Basta usar o cygwin com seu bash para muito mais funcionalidade.

Além disso: Você notou que a ajuda do build do MS Windows é um ótimo recurso para descrições da sintaxe da linha de comando do cmd?

Também dê uma olhada aqui: http://technet.microsoft.com/en-us/library/bb490890.aspx

Marco
fonte
21
%filee %subdirsó pode ser um caractere, ou seja %f, %s.
precisa saber é o seguinte
11
os 'subdiretórios no diretório atual' não estão funcionando. Eu recebo um erro: s foi inesperado no momento
Migrate2Lazarus ver meu perfil 26/02
78

Para iterar sobre cada arquivo, um loop for funcionará:

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

No meu caso, eu também queria o conteúdo do arquivo, o nome etc.

Isso levou a alguns problemas e achei que meu caso de uso poderia ajudar. Aqui está um loop que lê informações de cada arquivo '.txt' em um diretório e permite que você faça algo com ele (setx por exemplo).

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

* Limitação: val <= %% f só obterá a primeira linha do arquivo.

Aaron Votre
fonte
18
Ah, um exemplo de várias linhas. Obrigado por isso!
Nyerguds
@Aaron Votre Como terminar um loop?
Nijogeorgep
@nijogeorgep Você não precisa "terminar" o loop. No meu exemplo, tudo dentro dos parênteses (eco, etc) será executado uma vez para cada arquivo '* .txt' no diretório. Acho que a resposta que você está procurando pode ser melhor explicado aqui: stackoverflow.com/questions/1355791/...
Aaron Votre
@ Aaron Votre Eu estava tentando executar alguns comandos maven usando script, mas estava sendo executado como um loop infinito, então pedi. Comprar agora eu adicionei uma saída para meu loop e fixa o meu problema
nijogeorgep
@nijogeorgep Que bom que você descobriu!
Aaron Votre
57

Há uma diferença sutil entre executar a FORpartir da linha de comando e de um arquivo em lotes. Em um arquivo em lotes, você precisa colocar dois %caracteres na frente de cada referência de variável.

Em uma linha de comando:

FOR %i IN (*) DO ECHO %i

De um arquivo em lotes:

FOR %%i IN (*) DO ECHO %%i
aforia
fonte
44

Esse loop for listará todos os arquivos em um diretório.

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

"delims =" é útil para mostrar nomes de arquivos longos com espaços nele ....

'/ b "mostra apenas nomes, não datas de tamanho, etc.

Algumas coisas a saber sobre o argumento dir / a.

  • Qualquer uso de "/ a" listaria tudo, incluindo atributos ocultos e do sistema.
  • "/ ad" mostraria apenas subdiretórios, incluindo ocultos e do sistema.
  • O argumento "/ ad" elimina o conteúdo com o atributo 'D'irectory.
  • "/ adhs" mostrará tudo, mas as entradas com o atributo 'D'irectory,' H'idden 'S'ystem.

Se você usar isso na linha de comando, remova um "%".

Espero que isto ajude.

Jay
fonte
10

% 1 refere-se ao primeiro argumento transmitido e não pode ser usado em um iterador.

Tente o seguinte:

@echo off
for %%i in (*.*) do echo %%i
Sam Meldrum
fonte
Você está certo. Tentei, em modo imediato para verificar a sintaxe para e colado a linha reta para o esquecimento resposta sobre parâmetros :-)
Axeman
5
for %1 in (*.*) do echo %1

Tente "AJUDA" no cmd para obter um guia completo

Este é o guia para os comandos do XP. http://www.ss64.com/nt/

Axeman
fonte
4

Para percorrer todos os arquivos e pastas que você pode usar

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

Para percorrer todas as pastas apenas não com arquivos, você pode usar

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

Onde /sfornecerá todos os resultados em toda a árvore de diretórios em profundidade ilimitada. Você pode pular /sse desejar percorrer o conteúdo dessa pasta e não da subpasta

Implementando a pesquisa na iteração

Para iterar através de arquivos e pastas nomeados específicos, você pode procurar o nome e iterar usando o loop for

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

Para percorrer pastas / diretórios nomeados específicos e não arquivos , use /ADo mesmo comando

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

Eu tive problemas para obter a resposta do jop para trabalhar com um caminho absoluto até encontrar esta referência: https://ss64.com/nt/for_r.html

O exemplo a seguir percorre todos os arquivos em um diretório fornecido pelo caminho absoluto.

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

O código a seguir cria um arquivo chamado "AllFilesInCurrentDirectorylist.txt" no diretório atual, que contém a lista de todos os arquivos (somente arquivos) no diretório atual. Confira

dir /b /a-d > AllFilesInCurrentDirectorylist.txt
Ankur
fonte
3

Também poderia usar o comando forfiles :

forfiles /s 

e também verifique se é um diretório

forfiles /p c:\ /s /m *.* /c "cmd /c if @isdir==true echo @file is a directory"
Máx.
fonte
@isdir==trueprecisa ser@isdir==TRUE
psyklopz
2

Eu usaria vbscript (Windows Scripting Host), porque no lote tenho certeza de que você não pode dizer que um nome é um arquivo ou um diretório.

Em vbs, pode ser algo como isto:

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

Verifique FileSystemObject no MSDN .

Biri
fonte
Eu teria usado o perl para fazer isso. Infelizmente, não depende de mim.
Vhaerun 26/09/08
Alguma aplicação antiga? Coisas tristes.
Biri
Um desenvolvedor idiota viu arquivos em lote e pensou que eles eram a cura para todos os nossos problemas.
Vhaerun 26/09/08
11
@Vhaerun Uma vantagem do Windows Script Host (WSH) sobre o Perl seria que o WSH fosse pré-instalado com todas as versões do Windows, enquanto o Perl precisaria ser instalado separadamente, o que pode ou não ser uma opção viável em todos os casos.
Parampreet Dhatt
2

Eu uso o comando xcopy com a opção / L para obter os nomes dos arquivos. Portanto, se você deseja obter um diretório ou todos os arquivos no subdiretório, pode fazer algo assim:

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

Eu apenas uso o c: \ como destino, porque ele sempre existe nos sistemas Windows e não está copiando, portanto não importa. Se você quiser os subdiretórios, basta usar a opção / s no final. Você também pode usar as outras opções do xcopy se precisar delas por outros motivos.

Knoots
fonte
2

Tente isso para testar se um arquivo é um diretório:

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

Isso informará apenas se um arquivo NÃO é um diretório, o que também será verdadeiro se o arquivo não existir, portanto, verifique se o arquivo é necessário primeiro. Os sinais de intercalação (^) são usados ​​para escapar dos símbolos de redirecionamento e a saída da lista de arquivos é redirecionada para NUL para impedir que seja exibida, enquanto a saída de erro da listagem DIR é redirecionada para a saída para que você possa testar a mensagem da DIR "Arquivo não encontrado" "

sugerfunk
fonte
2

tente isto:

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

conta os arquivos .msi e .exe no seu diretório (e no subdiretório). Por isso, também faz a diferença entre pastas e arquivos como executáveis.

Basta adicionar uma extensão (.pptx .docx ..) se precisar filtrar outros arquivos no loop

Pequeno pônei
fonte
1

No meu caso, tive que excluir todos os arquivos e pastas abaixo de uma pasta temporária. Então foi assim que acabei fazendo isso. Eu tive que executar dois loops, um para arquivo e outro para pastas. Se arquivos ou pastas tiverem espaços em seus nomes, você precisará usar ""

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"
)
Sam B
fonte
1

Aqui está o meu ir com comentários no código.

Estou apenas aprimorando as habilidades de vingança, para perdoar qualquer erro flagrante.

Tentei escrever uma solução tudo em um da melhor maneira possível, com uma pequena modificação onde o usuário exige.

Algumas notas importantes: Apenas altere a variável recursivepara FALSEse você quiser apenas os arquivos e pastas dos diretórios raiz processados. Caso contrário, ele percorrerá todas as pastas e arquivos.

C&C muito bem-vindo ...

@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
Ste
fonte