Come eseguire il ciclo tra i file che corrispondono ai caratteri jolly nel file batch


194

Ho un set di nomi di file di base, per ogni nome 'f' ci sono esattamente due file, 'f.in' e 'f.out'. Voglio scrivere un file batch (in Windows XP) che attraversa tutti i nomi dei file, per ognuno dovrebbe:

  • Visualizza il nome base 'f'
  • Esegui un'azione su "f.in"
  • Esegui un'altra azione su "f.out"

Non ho modo di elencare il set di nomi di file di base, ad esempio cercare * .in (o * .out).


10
Non voglio davvero essere questo ragazzo dopo 111/0 voti, ma la tua domanda non mostra alcuna ricerca su Whatsoeaver
phil294

Risposte:


293

Supponendo di avere due programmi che elaborano i due file, process_in.exe e process_out.exe:

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

%% ~ nf è un modificatore di sostituzione che espande% f solo a un nome file. Vedi altri modificatori in https://technet.microsoft.com/en-us/library/bb490909.aspx (a metà della pagina) o solo nella risposta successiva.


47
Utilizzare un singolo '%' se si digita sulla riga di comando. So che l'OP non fa domande sulla riga di comando, ma è quello che stavo cercando quando questa domanda è arrivata all'inizio della mia ricerca su Google. Altri potrebbero apprezzare questo bit.
Jason,

2
Potresti spiegare la sintassi? La variabile loop viene dichiarata %%fperché è più %%~nftardi?
Colonnello Panic,

6
@ColonelPanic - ci sono alcuni ~modificatori per fare le cose, come nel mio esempio, basta ottenere il nome del file. È solo abitudine per me usarlo nel caso in cui *faccia il percorso completo o qualcosa del genere. Esistono alcuni modificatori (a metà pagina): microsoft.com/resources/documentation/windows/xp/all/proddocs/…
Jim Buck

cosa succede se il file e la directory contengono spazi?
BKSpurgeon,

3
Inoltre, tieni presente che la variabile %% f deve essere una singola lettera: verranno visualizzati messaggi di errore criptici se provi a utilizzare qualcosa di leggibile e significativo.
Bruce Dawson,

90

È possibile utilizzare questa riga per stampare il contenuto del desktop:

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

Una volta che hai la %%Ivariabile è facile eseguire un comando su di essa (basta sostituire la parola eco con il tuo programma)

Inoltre, è stata migliorata la sostituzione dei riferimenti alle variabili FOR È ora possibile utilizzare la sintassi opzionale seguente:

%~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

Negli esempi sopra %Ie PATH può essere sostituito da altri valori validi. La %~sintassi è terminata da un nome di variabile FOR valido. Scegliere nomi di variabili maiuscole come lo %Irende più leggibile ed evita confusione con i modificatori, che non fanno distinzione tra maiuscole e minuscole.

È possibile ottenere la documentazione completa digitando FOR /?


Questo non sembra funzionare. %%I was unexpected at this time.
Brad

4
@Brad se lo stai usando nella riga di comando (e non in un file batch), usa %Iinvece invece di%%I
doubleDown,

1
Una risposta molto migliore di quella accettata. Tutti i flag / modificatori inclusi nella risposta e non un sito Web di terze parti ( nessuno vuole fare clic sul collegamento, Louis )
JustCarty

5

Il modo più semplice, a mio modo di vedere, è usare un ciclo for che chiama un secondo file batch per l'elaborazione, passando a quel secondo file il nome base.

Secondo il per /? aiuto, basename può essere estratto usando l'opzione nifty ~ n. Quindi, lo script di base dovrebbe leggere:

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

Quindi, in process.cmd, supponi che% 0 contenga il nome di base e agisca di conseguenza. Per esempio:

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

Potrebbe esserci un modo migliore per farlo in uno script, ma sono sempre stato un po 'confuso su come estrarre più comandi in un singolo ciclo per un file batch.

EDIT: È fantastico! In qualche modo avevo perso la pagina nei documenti che mostravano che si potevano fare blocchi multi-linea in un ciclo FOR. Ho intenzione di tornare indietro e riscrivere alcuni file batch ora ...


4

Espansione sul posto di Nathans . Quanto segue eseguirà il lotto di lavoro in un file batch.

@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

3

Esiste uno strumento di solito utilizzato nei server MS (per quanto posso ricordare) chiamato forfile :

Il link sopra contiene aiuto e un link alla pagina di download di Microsoft.


1

Il codice seguente filtra i nomi di file che iniziano con una sottostringa specifica. Potrebbe essere modificato per soddisfare esigenze diverse lavorando sull'estrazione della sottostringa del sottotitolo e sull'istruzione 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

0

L'eco di f.in e f.out separerà il concetto di cosa eseguire il loop e cosa non eseguire il loop quando utilizzato in un ciclo 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
)

Anche se non hai chiesto, un buon modo per passare i comandi in f.in e f.out sarebbe quello di ...

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

Un collegamento a tutti i comandi di Windows XP: collegamento

Mi scuso se non ho risposto correttamente. La domanda era molto difficile per me da leggere.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.