2008-11-11 14 views
14

Potrzebuję pobrać nazwę folderu aktualnie wykonywanego pliku wsadowego. I starali się pętla nad bieżącym katalogu, używając następującej składni (co jest nie tak w chwili obecnej):Windows wsadowy - pętla nad folderem i sparsuj ostatnią nazwę folderu

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

kilka problemów na które ja nie potrafię przekazać „mydir” wartość zmiennej jako ciąg wyszukiwania . Wydaje się, że działa tylko wtedy, gdy przekazuję polecenia; Mam błędną składnię i nie mogę zrozumieć dlaczego.

Moje myśli polegały na pętli nad ciągiem folderów z ogranicznikiem "\", ale powoduje to również problemy. Jeśli ustawię zmienną w każdej pętli, ostatnią ustawioną wartością będzie nazwa bieżącego folderu. Na przykład, biorąc pod uwagę następującą ścieżkę:

C: \ Folder1 \ Folder2 \ folder3 \ Archive.bat

spodziewałbym się przeanalizować wartość 'folder3'.

Muszę przeanalizować tę wartość, ponieważ jej nazwa będzie częścią innego folderu, który zamierzam utworzyć w dalszej części pliku wsadowego.

Wielkie dzięki, jeśli ktoś może pomóc. Mogę szczekać na niewłaściwym drzewie, więc wszelkie inne podejścia również zostaną bardzo dobrze przyjęte.

Odpowiedz

10

Byliście bardzo blisko niego :) To powinno działać:

@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 

Z jakiegoś powodu na komendzie nie lubi „\” jako separatora, więc przekształcone wszystko „\” do „; " Pierwsze (SET mydir=%mydir:\=;%)

+1

Lubi '|' dobrze jako separator, musisz po prostu wstawić% mydir% w cudzysłowie, jak w '%% i IN ("% mydir% ")' – ErikE

0

W plikach wsadowych w poleceniu FOR należy dodać% cokolwiek z dodatkowym% (na przykład %%).

'echo% ~ p0' wydrukuje bieżący katalog pliku wsadowego.

+0

nie, wypisze całą ścieżkę do bieżącego katalogu minus literę dysku. – djangofan

+0

@djangofan zamierzasz głosować w dół semantyką? – kenny

+0

Nigdy bym nie oddał głosu, który spowodowałby, że twoja odpowiedź miała "-1". Ale z drugiej strony, nie będąc tym, czego chciał pytający, odpowiedź też nie zasługiwała na "1". – djangofan

0

To co mieliśmy w końcu (trochę bardziej surowy i można tylko iść tak głęboko :)

@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

Nieznaczne zmiany na ewentualne foldery mają spacje w nazwie - zastąpić przestrzeń „:” przed i po operacji:

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

To nie jest potrzebne. Po prostu umieść cudzysłowy wokół% mydir% w instrukcji for. – ErikE

0

nie wiem, czy jest to wersja Windows jestem na (win2k3), ale dla pętli nie daje mi coś pożytecznego dla próbuje iterować przez pojedynczy ciąg. Zgodnie z moją obserwacją (i informacją FOR /?) Otrzymujesz jedną iterację dla każdego wiersza wejścia do FOR i nie ma możliwości zmiany tego na iterację w linii. Możesz rozbić na wiele tokenów dla danej linii, ale jest to tylko jedno wywołanie ciała pętli FOR.

Uważam, że podejście CALL: LABEL w tych odpowiedziach to świetna robota. Coś, czego nie wiedziałem, dopóki nie spojrzałem na to, było ";" i "," są rozpoznawane jako separatory argumentów. Więc po zastąpieniu odwróconych ukośników średnikami, możesz zadzwonić do swojej etykiety i powtórzyć ją za pomocą SHIFT.

W ten sposób pracuję nad tym, co napisali tutaj inni, mam poniższe rozwiązanie. Zamiast przechwytywania nazwy ostatniego folderu, faktycznie chciałem znaleźć wszystko aż do jakiejś znanej nazwy katalogu. To jest to, co zaimplementowano poniżej.

@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

To pytanie jest trochę stare, ale szukałem rozwiązania więcej niż jeden raz, więc przedstawiłem zupełnie nowe podejście, które właśnie opracowałem.

Sztuką jest, że wybieramy żądaną ścieżkę, zrób kopię zapasową o jeden poziom, aby stworzyć maskę folderu do zamiany, a następnie zastąp maskę folderu nic.

Aby to przetestować, wystarczy skopiować i wkleić skrypt poleceń (.cmd) do dowolnego katalogu, a następnie go uruchomić. Będzie to wypluć tylko najgłębsze katalogu w którym aktualnie jesteś

Uwagi:.

  • Zamiana% ~ dp0 z co ścieżka chcesz (jak to jest, zwróci najgłębszy folderu plik wsadowy jest run from. To nie jest to samo co% cd%.)
  • Podczas określania zmiennej 'pathtofind' upewnij się, że nie ma żadnych notowań np. c: \ jakaś ścieżka, a nie "c: \ jakaś ścieżka".
  • Oryginalny pomysł folderu maskowania jest moje
  • spacji w ścieżce nie są problemem
  • głębokość Folder nie jest problemem
  • To było możliwe dzięki geniuszowi tej partii końcówki skryptowego http://www.dostips.com/DtCodeBatchFiles.php#Batch.FindAndReplace

Mam nadzieję, że to pomoże komuś innemu!

Dzięki,

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

Niestety, to działa tylko wtedy, gdy wielki umieścić na pewnej głębokości, ale mają problemy z byciem na samym szczycie góry ... Wprowadzenie tego programu do "C: \ Windows" np wyniknie z ... "C: \ Windows", nie oczekuje się "Windows". Nadal świetną robotę, a nadal można naprawić uszkodzenia. Moje podejście:

@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 

I to działa dobrze dla mnie teraz, dzięki za pomysł, szukałem czegoś takiego od dłuższego czasu.

jeth

+1

Ojej, kopiowanie odpowiedzi innych ludzi jest trochę tandetne. – ErikE

1

Sheesh chłopaki, co za bałagan. Jest to dość łatwe i szybciej można to zrobić w pamięci bez płyty CD.

Otrzymuje dwa ostatnie katalogi ścieżki. Zmodyfikuj go zgodnie z wymaganiami, aby uzyskać ostatnie tokeny dowolnej linii. Mój oryginalny kod, na którym to oparłem, ma większą złożoność dla moich własnych celów.

Fyi, prawdopodobnie nie pozwala na ścieżki z wykrzyknikami, ponieważ używam enabledelayedexpansion, ale można to naprawić.

Nie działa również na zwykłym dysku głównym. Można temu zapobiec na wiele sposobów. Sprawdź, co kończy się ścieżka wejściowa lub licznik, lub modyfikuj zachowanie tokena i sprawdzania itp.

@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

Po zmaga się z niektórymi z tych sugestii, znalazłem powodzeniem stosowane następujące 1 wykładzinę (w Windows 2008)

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

To zadziałało również dla mnie. – kindall

+1

Nie udało się, gdy nazwa pliku zawiera spację. Proszę dodać podwójne cudzysłowy wokół! FullPath! aby to zadziałało – Rupin

+0

_Sweet_. Dzięki.Oto, jak go użyłem: 'for/d %% P in (% IndividualProjectsFolder% \ *) do %% F in (%% P) do 7z a% TempRootFolder% \ ZIPs \ CADblokeCADtoolFor %% ~ nxF.zip% IndividualProjectsFolder% \ %% ~ nxF \ '(awaria oceny) –

2

3 linie skryptu Pobiera wynik ...

Znaleziono 2 dodatkowe sposoby osiągnięcia tego celu, w przeciwieństwie do innych odpowiedzi na to pytanie, nie wymaga żadnych "funkcji" wsadowych, opóźnionego rozszerzenia, a także nie ma ograniczenia, które ma odpowiedź Tima Peela na głębokość katalogu:

@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 

ZMIAN: po moim nowym revsion, tutaj znajduje się przykładowe wyjście:

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

Oznacza to, że skrypt nie obsługuje „#” lub „” w nazwie folderu, ale może być regulowana aby to zrobić.

Uzupełnienie: Po prosząc kogoś na forum dostips, znalazł jeszcze łatwiejszy sposób, aby to zrobić:

@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

Nie korzystałem z opóźnionego rozszerzenia ani funkcji "wsadowych", ale w wielu przypadkach to się nie udawało, np. 'C: \', 'C: \ myPath, with, comma',' C: \ Documents & Settings' i 'C: \ myPath_with_underscores' – jeb

+0

Są to przypadki skrajne, które są niezwykle rzadkie w scenerio rzeczywistym świecie. Problem podkreślenia jest bardziej powszechny i ​​można go łatwo obejść. Zaktualizuję moją odpowiedź, aby to pomieścić. – djangofan

+2

Powinieneś używać składni quotd w swoich zestawach instrukcji, w przeciwnym razie masz problemy ze znakami specjalnymi, takimi jak '&'. Zamiast 'SET CDIR =% ~ p0' wypróbuj go za pomocą' SET "CDIR =% ~ p0" 'i' SET "_CDIR =% CDIR: ~ 1, -1%" ' – jeb

2

Aby powrócić do oryginalnego plakatu wydania:

Na przykład, biorąc pod uwagę następujące ścieżka: C: \ Folder1 \ Folder2 \ Folder3 \ Archive.bat Spodziewam się przetworzyć wartość "Folder3".

Proste rozwiązanie to jest:

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

da 'folder3'. Plik/ścieżka nie musi istnieć. Oczywiście .... dla rodzica nadrzędnego, lub ...... dla powyższego (i tak dalej) też działa.

6

Znalazłem ten stary wątek, kiedy szukałem ostatniego segmentu bieżącego katalogu. Dotychczasowe pisarze odpowiedzi doprowadziły mnie do następującego:

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

jak poprzednie wyjaśniły, nie zapomnij umieścić w cudzysłowie żadnych ścieżek tworzyć z% _LAST_SEGMENT_% (tak jak ja z% CD% w moim przykładzie).

Mam nadzieję, że to pomoże komuś ...

Powiązane problemy