2008-11-11 4 views
14

Je dois saisir le nom du dossier d'un fichier de traitement en cours d'exécution. Je suis en train de boucler sur le répertoire courant en utilisant la syntaxe suivante (ce qui est faux à l'heure actuelle):Windows batch - boucle sur la chaîne du dossier et analyse le nom du dernier dossier

set mydir = %~p0 
for /F "delims=\" %i IN (%mydir%) DO @echo %i 

Couple de questions dans ce que je ne peux pas sembler passer le « monrep » valeur variable comme la chaîne de recherche . Cela ne semble fonctionner que si je passe des commandes; J'ai la syntaxe erronée et je n'arrive pas à comprendre pourquoi. Je pensais à boucler sur la chaîne du dossier avec un délimiteur '\' mais cela posait aussi des problèmes. Si je définis une variable sur chaque boucle, la dernière valeur définie sera le nom du dossier actuel. Par exemple, étant donné le chemin suivant:

C: \ Dossier1 \ Dossier2 \ Folder3 \ Archive.bat

j'attendre à analyser la valeur 'Folder3'.

Je dois analyser cette valeur car son nom fera partie d'un autre dossier que je vais créer plus bas dans le fichier séquentiel.

Un grand merci si quelqu'un peut vous aider. Il se peut que j'aboie complètement le mauvais arbre, de sorte que d'autres approches seraient grandement reçues.

Répondre

10

Vous étiez assez près de lui :) Cela devrait fonctionner:

@echo OFF 
set mydir="%~p0" 
SET mydir=%mydir:\=;% 

for /F "tokens=* delims=;" %%i IN (%mydir%) DO call :LAST_FOLDER %%i 
goto :EOF 

:LAST_FOLDER 
if "%1"=="" (
    @echo %LAST% 
    goto :EOF 
) 

set LAST=%1 
SHIFT 

goto :LAST_FOLDER 

Pour une raison quelconque pour la commande n'aime pas « \ » comme séparateur, donc je convertis tout « \ » à « ; ' premier (SET mydir=%mydir:\=;%)

+1

Il aime bien '' 'comme délimiteur, il suffit de mettre% mydir% entre guillemets comme dans '%% i IN ("% mydir% ")' – ErikE

0

Dans les fichiers batch de la commande FOR, vous devrez ajouter% prepend à un% supplémentaire (par exemple %% quel que soit). 'Echo% ~ p0' affichera le répertoire en cours du fichier de commandes

+0

Non, il imprime le chemin complet du répertoire courant moins la lettre du lecteur. – djangofan

+0

@djangofan vous allez baisser la sémantique? – kenny

+0

Je n'aurais jamais donné un vote qui aurait abouti à votre réponse ayant un "-1". Mais, d'un autre côté, n'étant pas ce que le questionneur voulait, votre réponse ne méritait pas non plus un "1". – djangofan

0

C'est ce que nous avions à la fin (peu plus brut et ne peut aller si profond :)

@echo off 
for /f "tokens=1-10 delims=\" %%A in ('echo %~p0') do (
    if NOT .%%A==. set new=%%A 
    if NOT .%%B==. set new=%%B 
    if NOT .%%C==. set new=%%C 
    if NOT .%%D==. set new=%%D 
    if NOT .%%E==. set new=%%E 
    if NOT .%%F==. set new=%%F 
    if NOT .%%G==. set new=%%G 
    if NOT .%%H==. set new=%%H 
    if NOT .%%I==. set new=%%I 
    if NOT .%%J==. set new=%%J 
) 

@echo %new% 
1

altération légère car si l'un des dossiers ont des espaces dans leurs noms - remplacer l'espace à « : » avant et après l'opération:

set mydir="%~p0" 
set mydir=%mydir:\=;% 
set mydir=%mydir: =:% 

for /F "tokens=* delims=;" %%i IN (%mydir%) DO call :LAST_FOLDER %%i 
goto :EOF 

:LAST_FOLDER 
if "%1"=="" (
    set LAST=%LAST::= % 
    goto :EOF 
) 

set LAST=%1 
SHIFT 

goto :LAST_FOLDER 
+0

Ceci n'est pas nécessaire. Placez simplement des guillemets autour de% mydir% dans l'instruction for. – ErikE

0

Je ne sais pas si c'est la version de windows que je suis sur (win2k3), mais la boucle FOR ne me donne pas quelque chose d'utile pour essayer Itérer à travers une seule chaîne. Selon mon observation (et l'info FOR /?) Vous obtenez une itération pour chaque ligne d'entrée à FOR, et il n'y a aucun moyen de changer cela pour itérer dans une ligne. Vous pouvez rompre en plusieurs jetons pour une ligne donnée, mais ce n'est qu'une invocation du corps de la boucle FOR.

Je pense que l'approche CALL: LABEL dans ces réponses fait un excellent travail. Quelque chose que je ne savais pas avant de regarder cela était que ";" et "," sont tous les deux reconnus comme des séparateurs d'arguments. Ainsi, une fois que vous remplacez les barres obliques inverses par des points-virgules, vous pouvez appeler votre étiquette et parcourir avec SHIFT.

Donc travailler hors de ce qui est posté par d'autres ici, j'ai la solution ci-dessous. Au lieu de saisir le dernier nom de dossier, je voulais en fait tout trouver jusqu'à un nom de répertoire connu ... c'est ce qui est implémenté ci-dessous.

@echo off 
if "%1"=="" goto :USAGE 

set FULLPATH=%~f1 
set STOPDIR=%2 
set PATHROOT= 

:: Replace backslashes with semicolons 
set FULLPATH=%FULLPATH:\=;% 

:: Iterate through path (the semicolons cause each dir name to be a new argument) 
call :LOOP %FULLPATH% 
goto :EOF 

:LOOP 

::Exit loop if reached the end of the path, or the stop dir 
if "%1"=="" (goto :EOF) 
if "%1"=="%STOPDIR%" (goto :EOF) 

::If this is the first segment of the path, set value directly. Else append. 
if not defined PATHROOT (set PATHROOT=%1) else (set PATHROOT=%PATHROOT%\%1) 

::shift the arguments - the next path segment becomes %i 
SHIFT 

goto :LOOP 

:USAGE 
echo Usage: 
echo %~0 ^<full path to parse^> ^<dir name to stop at^> 
echo E.g. for a command: 
echo %~0 c:\root1\child1\child2 child2 
echo The value of c:\root1\child1 would be assigned to env variable PATHROOT 
4

Cette question est un peu vieux, mais j'ai cherché une solution plus d'une fois voici donc un tout nouveau prendre à ce que je viens de mettre ensemble.

L'astuce est que nous prenons le chemin souhaité, sauvegarder un niveau pour créer un masque de dossier pour la substitution, puis remplacer le masque de dossier par rien.

Pour le tester, copiez et collez simplement dans un script de commande (.cmd) dans n'importe quel répertoire, puis exécutez-le. Il recracher que le répertoire le plus profond que vous êtes actuellement à

Notes:.

  • Remplacer% ~ dp0 avec tout ce chemin que vous aimez (comme il est, il retourne le plus profond dossier du fichier de commandes est Ce n'est pas la même chose que% cd%.)
  • Lors de la spécification de la variable 'pathtofind', assurez-vous qu'il n'y a pas de guillemets, par ex. c: \ un chemin et pas "c: \ un chemin".
  • L'idée originale de masquage du dossier est à moi
  • Les espaces dans le chemin ne posent aucun problème
  • profondeur du dossier n'est pas un problème
  • Il a été rendu possible par le génie de cette astuce de script batch http://www.dostips.com/DtCodeBatchFiles.php#Batch.FindAndReplace

Espérons que cela aide quelqu'un d'autre!

Merci,

John D

@echo off 
set pathtofind=%~dp0 
if not exist %pathtofind% echo Path does not exist&pause>nul&goto :eof 

cd /d %pathtofind% 
set path1=%cd% 
cd .. 
set path2=%cd% 

call set "path3=%%path1:%path2%\=%%" 

echo %path3% 

pause>nul 
-2

Unfortunatelly, cela fonctionne grand que lorsqu'il est mis sur une certaine profondeur mais ont des problèmes d'être au sommet de la montagne ... réalisation de ce programme "C: \ Windows" par exemple résultera avec ... "C: \ Windows", pas attendu "Windows". Encore un excellent travail, et encore des dommages peuvent être réparés. Mon approche:

@echo off 
set pathtofind=%~dp0 
if not exist %pathtofind% echo Path does not exist&pause>nul&goto :eof 

cd /d %pathtofind% 
set path1=%cd% 
cd .. 
set path2=%cd% 
set path4=%~dp1 
call set "path3=%%path1:%path2%\=%%" 
call set "path5=%%path3:%path4%*\=%%" 
echo %path5% 

pause>nul 

Et cela fonctionne très bien pour moi maintenant, merci pour l'idée, je cherchais quelque chose comme ça pendant un certain temps.

jeth

+1

Gee, copier les réponses des autres est un peu ringard. – ErikE

1

gars sheesh, quel gâchis. C'est assez facile, et c'est plus rapide de le faire en mémoire sans CD.

Ceci obtient les deux derniers répertoires d'un chemin. Modifiez-le si nécessaire pour obtenir les derniers jetons de n'importe quelle ligne. Mon code original basé sur ceci a plus de complexité pour mes propres buts. Fyi, cela ne permet probablement pas les chemins avec des points d'exclamation puisque j'utilise enabledelayedexpansion, mais cela pourrait être corrigé.

Il ne fonctionnera pas non plus sur une racine de lecteur simple. Cela pourrait être évité de plusieurs façons. Vérifiez à quoi se termine le chemin d'entrée, ou un compteur, ou modifiez le jeton et vérifiez le comportement, etc.

@echo off&setlocal enableextensions,enabledelayedexpansion 

call :l_truncpath "C:\Windows\temp" 

---------- 

:l_truncpath 
set "_pathtail=%~1" 
:l_truncpathloop 
for /f "delims=\ tokens=1*" %%x in ("!_pathtail!") do (
if "%%y"=="" (
set "_result=!_path!\!_pathtail!" 
echo:!_result! 
exit/b 
) 
set "_path=%%x" 
set "_pathtail=%%y" 
) 
goto l_truncpathloop 
18

Après avoir lutté avec certaines de ces suggestions, j'ai trouvé un utilisé avec succès le 1 revêtement suivant (dans Windows 2008)

for %%a in (!FullPath!) do set LastFolder=%%~nxa 
+0

Cela a très bien fonctionné pour moi aussi. – kindall

+1

Cela a échoué lorsque le nom du fichier contient un espace. Veuillez ajouter des guillemets doubles! FullPath! pour que cela fonctionne – Rupin

+0

_Sweet_. Merci.Voici comment je l'ai utilisé 'pour/d %% P dans (% IndividualProjectsFolder% \ *) faire pour %% F dans (%% P) faire 7z a% TempRootFolder% \ ZIPs \ CADblokeCADtoolFor %% ~ nxF.zip% IndividualProjectsFolder% \ %% ~ nxF \ '(échec de la correction) –

2

3 lignes de script est le résultat ...

Trouvé 2 façons supplémentaires d'atteindre l'objectif, et contrairement aux autres réponses à cette question, il ne nécessite pas de «fonctions» par lots, pas d'expansion retardée, et n'a pas la limitation que la réponse de Tim Peel a avec profondeur d'annuaire:

@echo off 
SET CDIR=%~p0 
SET CDIR=%CDIR:~1,-1% 
SET CDIR=%CDIR:\=,% 
SET CDIR=%CDIR: =#% 
FOR %%a IN (%CDIR%) DO SET "CNAME=%%a" 
ECHO Current directory path: %CDIR% 
SET CNAME=%CNAME:#= % 
ECHO Current directory name: %CNAME% 
pause 

Révision: après mon nouveau revsion, voici un exemple de sortie:

Current directory path: Documents#and#Settings,username,.sqldeveloper,tmp,my_folder,MY.again 
Current directory name: MY.again 
Press any key to continue . . . 

Cela signifie que le script ne gère pas « # » ou « » dans un nom de dossier, mais peut être ajustée faire cela.

ADDENDA: Après avoir demandé quelqu'un dans le forum dostips, a trouvé un moyen encore plus facile de le faire:

@echo off 
SET "CDIR=%~dp0" 
:: for loop requires removing trailing backslash from %~dp0 output 
SET "CDIR=%CDIR:~0,-1%" 
FOR %%i IN ("%CDIR%") DO SET "PARENTFOLDERNAME=%%~nxi" 
ECHO Parent folder: %PARENTFOLDERNAME% 
ECHO Full path: %~dp0 
pause>nul 
+0

Il n'a pas utilisé d'extension retardée ni de "fonctions" par lots, mais pour cela il échoue dans beaucoup de cas, comme 'C: \', 'C: \ myPath, avec, comma',' C: \ Documents & Settings' et 'C: \ myPath_with_underscores' – jeb

+0

Ce sont des cas marginaux qui sont extrêmement rares dans un monde réel. Le problème de soulignement est plus commun et peut facilement être travaillé autour. Je vais mettre à jour ma réponse pour accommoder celui-là. – djangofan

+2

Vous devez utiliser la syntaxe quotd dans vos instructions set, sinon vous avez des problèmes avec des caractères spéciaux comme '&'. Au lieu de 'SET CDIR =% ~ p0', essayez-le avec' SET 'CDIR =% ~ p0 "' et 'SET' _CDIR =% CDIR: ~ 1, -1%" ' – jeb

2

Pour revenir à la question de l'affiche originale:

Par exemple, compte tenu de ce qui suit chemin: C: \ Folder1 \ Folder2 \ Folder3 \ Archive.bat Je m'attendrais à analyser la valeur 'Folder3'.

La solution simple pour cela est:

for /D %%I in ("C:\Folder1\Folder2\Folder3\Archive.bat\..") do echo parentdir=%%~nxI 

donnera 'Folder3'. Le fichier/chemin n'a pas besoin d'exister. Bien sûr, .... pour le parent du parent, ou ...... pour celui au-dessus (et ainsi de suite) aussi.

6

J'ai trouvé cet ancien thread lorsque je cherchais le dernier segment du répertoire courant. Les auteurs réponses précédentes me conduisent à ce qui suit:

FOR /D %%I IN ("%CD%") DO SET _LAST_SEGMENT_=%%~nxI 
ECHO Last segment = "%_LAST_SEGMENT_%" 

Comme précédentes ont expliqué, ne pas oublier de mettre des guillemets autour des chemins créer avec% _LAST_SEGMENT_% (comme je l'ai fait avec%% CD dans mon exemple).

Espérons que cela aide quelqu'un ...

Questions connexes