Como percorrer os arquivos que correspondem ao curinga no arquivo em lotes

193

Eu tenho um conjunto de nomes de arquivos base, para cada nome 'f' existem exatamente dois arquivos, 'f.in' e 'f.out'. Quero escrever um arquivo em lotes (no Windows XP) que revise todos os nomes de arquivos, para cada um deles:

  • Exiba o nome base 'f'
  • Execute uma ação em 'f.in'
  • Execute outra ação em 'f.out'

Não tenho como listar o conjunto de nomes de arquivos base, além de procurar * .in (ou * .out), por exemplo.

Luke Halliwell
fonte
10
Eu realmente não quero ser esse cara depois 111/0 votos, mas a sua pergunta não mostra qualquer reasearch whatsoeaver
phil294

Respostas:

292

Supondo que você tenha dois programas que processam os dois arquivos, process_in.exe e process_out.exe:

for %%f in (*.in) do (
    echo %%~nf
    process_in "%%~nf.in"
    process_out "%%~nf.out"
)

%% ~ nf é um modificador de substituição que expande% f apenas para um nome de arquivo. Veja outros modificadores em https://technet.microsoft.com/en-us/library/bb490909.aspx (no meio da página) ou apenas na próxima resposta.

Jim Buck
fonte
47
Use um único '%' se digitar isso na linha de comando. Eu sei que o OP não pergunta sobre a linha de comando, mas era isso que eu estava procurando quando essa pergunta surgiu no topo da minha pesquisa no Google. Outros podem apreciar este pouco.
28415 Jason
2
Você poderia explicar a sintaxe? A variável loop é declarada %%fpor que é mais %%~nftarde?
Coronel Panic
6
@ ColonelPanic - existem alguns ~modificadores para fazer as coisas, como no meu exemplo, basta obter o nome do arquivo. É apenas um hábito para mim usar isso no caso de *fazer o caminho completo ou algo assim. Existem alguns desses modificadores (no meio da página): microsoft.com/resources/documentation/windows/xp/all/proddocs/…
Jim Buck
e se o arquivo e o diretório tiverem espaços?
precisa saber é o seguinte
3
Além disso, esteja ciente de que a variável %% f deve ser uma única letra - mensagens de erro criptográficas aparecerão se você tentar usar algo legível e significativo.
Bruce Dawson
90

Você pode usar esta linha para imprimir o conteúdo da sua área de trabalho:

FOR %%I in (C:\windows\desktop\*.*) DO echo %%I 

Depois de ter a %%Ivariável, é fácil executar um comando nela (basta substituir a palavra eco pelo seu programa)

Além disso, a substituição das referências de variáveis ​​FOR foi aprimorada. Agora você pode usar a seguinte sintaxe opcional:

%~I         - expands %I removing any surrounding quotes (")
%~fI        - expands %I to a fully qualified path name
%~dI        - expands %I to a drive letter only
%~pI        - expands %I to a path only (directory with \)
%~nI        - expands %I to a file name only
%~xI        - expands %I to a file extension only
%~sI        - expanded path contains short names only
%~aI        - expands %I to file attributes of file
%~tI        - expands %I to date/time of file
%~zI        - expands %I to size of file
%~$PATH:I   - searches the directories listed in the PATH
               environment variable and expands %I 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

https://ss64.com/nt/syntax-args.html

Nos exemplos acima, %IPATH pode ser substituído por outros valores válidos. A %~sintaxe é finalizada por um nome de variável FOR válido. Escolher nomes de variáveis ​​em maiúsculas como o %Itorna mais legível e evita confusão com os modificadores, que não diferenciam maiúsculas de minúsculas.

Você pode obter a documentação completa digitando FOR /?

Mark Ingram
fonte
Isso não parece funcionar. %%I was unexpected at this time.
Brad
4
@ Brad se você estiver usando isso na linha de comando (e não em um arquivo de lote), em seguida, usar %I, em vez de%%I
DoubleDown
1
Uma resposta muito melhor do que a aceita. Todas as bandeiras / modificadores incluídos dentro a resposta e não um site de terceiros ( ninguém quer clicar em seu link, Louis )
JustCarty
5

A maneira mais fácil, a meu ver, é usar um loop for que chame um segundo arquivo em lotes para processamento, passando para o segundo arquivo o nome base.

De acordo com o / /? ajuda, o nome da base pode ser extraído usando a opção nifty ~ n. Portanto, o script base seria:

for %%f in (*.in) do call process.cmd %%~nf

Em process.cmd, suponha que% 0 contenha o nome da base e aja de acordo. Por exemplo:

echo The file is %0
copy %0.in %0.out
ren %0.out monkeys_are_cool.txt

Pode haver uma maneira melhor de fazer isso em um script, mas sempre fiquei um pouco confuso sobre como puxar vários comandos em um único loop for em um arquivo em lotes.

EDIT: Isso é fantástico! De alguma forma, havia perdido a página nos documentos que mostravam que era possível fazer blocos de várias linhas em um loop FOR. Vou precisar voltar e reescrever alguns arquivos em lotes agora ...

Nathan Fritz
fonte
4

Expandindo no post de Nathans . A seguir, o lote será executado em um arquivo em lotes.

@echo off

if %1.==Sub. goto %2

for %%f in (*.in) do call %0 Sub action %%~nf
goto end

:action
echo The file is %3
copy %3.in %3.out
ren %3.out monkeys_are_cool.txt

:end
Martin
fonte
3

Existe uma ferramenta geralmente usada nos servidores MS (pelo que me lembro) chamada forfiles :

O link acima contém ajuda e também um link para a página de download da microsoft.


fonte
1

O código abaixo filtra os nomes de arquivos iniciados com a subsequente substring. Ele pode ser alterado para atender a diferentes necessidades, trabalhando na extração de substring de sub-nome e na instrução IF:

echo off
rem filter all files not starting with the prefix 'dat'
setlocal enabledelayedexpansion
FOR /R your-folder-fullpath %%F IN (*.*) DO (
set fname=%%~nF
set subfname=!fname:~0,3!
IF NOT "!subfname!" == "dat" echo "%%F"
)
pause
Sandro Rosa
fonte
0

O eco de f.in e f.out separará o conceito do que fazer loop e do que não fazer loop quando usado em um loop for / f.

::Get the files seperated
echo f.in>files_to_pass_through.txt
echo f.out>>files_to_pass_through.txt

for /F %%a in (files_to_pass_through.txt) do (
for /R %%b in (*.*) do (
if "%%a" NEQ "%%b" (
echo %%b>>dont_pass_through_these.txt
)
)
)
::I'm assuming the base name is the whole string "f".
::If I'm right then all the files begin with "f".
::So all you have to do is display "f". right?
::But that would be too easy.
::Let's do this the right way.
for /f %%C in (dont_pass_through_these.txt)
::displays the filename and not the extention
echo %~nC
)

Embora você não tenha perguntado, uma boa maneira de passar comandos para f.in e f.out seria ...

for /F %%D "tokens=*" in (dont_pass_through_these.txt) do (
for /F %%E in (%%D) do (
start /wait %%E
)
)

Um link para todos os comandos do Windows XP: link

Peço desculpas se não respondi corretamente. A pergunta foi muito difícil para mim ler.

Z. Mickaels
fonte