Comment parcourir les fichiers correspondant au caractère générique dans un fichier de commandes


193

J'ai un ensemble de noms de fichiers de base, pour chaque nom «f», il y a exactement deux fichiers, «f.in» et «f.out». Je veux écrire un fichier batch (sous Windows XP) qui passe par tous les noms de fichiers, pour chacun il doit:

  • Afficher le nom de base «f»
  • Effectuer une action sur 'f.in'
  • Effectuez une autre action sur 'f.out'

Je n'ai aucun moyen de lister l'ensemble des noms de fichiers de base, sauf pour rechercher * .in (ou * .out) par exemple.


10
Je ne veux vraiment pas être ce type après 111/0 votes, mais votre question ne montre aucune recherche quoi que ce soit
phil294

Réponses:


292

En supposant que vous ayez deux programmes qui traitent les deux fichiers, process_in.exe et process_out.exe:

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

%% ~ nf est un modificateur de substitution, qui étend% f à un nom de fichier uniquement. Voir d'autres modificateurs dans https://technet.microsoft.com/en-us/library/bb490909.aspx (au milieu de la page) ou juste dans la réponse suivante.


47
Utilisez un seul «%» si vous le saisissez sur la ligne de commande. Je sais que l'OP ne pose pas de questions sur la ligne de commande, mais c'est ce que je cherchais lorsque cette question est apparue en haut de ma recherche Google. D'autres peuvent apprécier ce morceau.
Jason

2
Pourriez-vous expliquer la syntaxe? La variable de boucle est déclarée %%fpourquoi est-elle %%~nfplus tard?
Colonel Panic

6
@ColonelPanic - il y a une poignée de ~modificateurs pour faire des choses, comme dans mon exemple, il suffit d'obtenir le nom de fichier. C'est juste une habitude pour moi de l'utiliser au cas où le *chemin complet ou quelque chose. Il existe une poignée de ces modificateurs (au milieu de la page): microsoft.com/resources/documentation/windows/xp/all/proddocs/…
Jim Buck

que faire si le fichier et le répertoire contiennent des espaces?
BKSpurgeon

3
Sachez également que la variable %% f doit être une seule lettre - des messages d'erreur cryptiques apparaîtront si vous essayez d'utiliser quelque chose de lisible et significatif.
Bruce Dawson

90

Vous pouvez utiliser cette ligne pour imprimer le contenu de votre bureau:

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

Une fois que vous avez la %%Ivariable, il est facile d'exécuter une commande dessus (remplacez simplement le mot echo par votre programme)

De plus, la substitution des références de variable FOR a été améliorée. Vous pouvez désormais utiliser la syntaxe facultative suivante:

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

Dans les exemples ci-dessus %I, PATH peut être remplacé par d'autres valeurs valides. La %~syntaxe se termine par un nom de variable FOR valide. Choisir des noms de variables majuscules comme le %Irend plus lisible et évite la confusion avec les modificateurs, qui ne sont pas sensibles à la casse.

Vous pouvez obtenir la documentation complète en tapant FOR /?


Cela ne semble pas fonctionner. %%I was unexpected at this time.
Brad

4
@Brad si vous l'utilisez dans la ligne de commande (et non dans un fichier de commandes), utilisez %Iplutôt au lieu de%%I
doubleDown

1
Une bien meilleure réponse que l'acceptation. Tous les indicateurs / modificateurs inclus dans la réponse et non un site Web tiers ( personne ne veut cliquer sur votre lien, Louis )
JustCarty

5

Le moyen le plus simple, selon moi, est d'utiliser une boucle for qui appelle un deuxième fichier de commandes pour le traitement, en transmettant à ce deuxième fichier le nom de base.

Selon le pour /? aide, le nom de base peut être extrait à l'aide de l'option nifty ~ n. Ainsi, le script de base se lirait:

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

Ensuite, dans process.cmd, supposez que% 0 contient le nom de base et agissez en conséquence. Par exemple:

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

Il pourrait y avoir une meilleure façon de le faire dans un script, mais j'ai toujours été un peu flou sur la façon de tirer plusieurs commandes en une seule boucle for dans un fichier batch.

EDIT: C'est fantastique! J'avais en quelque sorte manqué la page des documents qui montrait que vous pouviez faire des blocs multi-lignes dans une boucle FOR. Je vais devoir revenir en arrière et réécrire certains fichiers batch maintenant ...


4

Expansion sur le poste de Nathans . Ce qui suit fera le lot de travaux dans un fichier de commandes.

@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

Il y a un outil habituellement utilisé dans les serveurs MS (pour autant que je m'en souvienne) appelé forfiles :

Le lien ci-dessus contient de l'aide ainsi qu'un lien vers la page de téléchargement de Microsoft.


1

Le code ci-dessous filtre les noms de fichiers commençant par une sous-chaîne donnée. Il peut être modifié pour répondre à différents besoins en travaillant sur l'extraction de sous-chaîne de sous-nom et l'instruction 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

Faire écho à f.in et f.out séparera le concept de ce qu'il faut boucler et de ce qu'il ne faut pas boucler lorsqu'il est utilisé dans une boucle 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
)

Bien que vous ne l'ayez pas demandé, un bon moyen de passer des commandes en f.in et f.out serait de ...

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

Un lien vers toutes les commandes de Windows XP: lien

Je m'excuse si je n'ai pas répondu correctement à cette question. La question était très difficile à lire pour moi.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.