Jak usunąć określone znaki z początku i końca nazw plików?
Skrypciarze odpowiadają na Wasze pytania
Witamy w rubryce TechNet, w której Skrypciarze z firmy Microsoft odpowiadają na częste pytania dotyczące używania skryptów w administracji systemu. Jeśli macie jakieś pytania z tej dziedziny, zachęcamy do wysłania e-maila na adres: scripter@microsoft.com. Nie możemy zagwarantować odpowiedzi na każde otrzymane pytanie, ale staramy się jak możemy. |
CONTENT
Jak usunąć określone znaki z początku i końca nazw plików?
Cześć, Skrypciarze! Jak skrócić nazwy plików, usuwając powtarzający się w nich początek i koniec i pozostawiając ich unikatowe, środkowe części?
-- RE
Cześć, RE. Zanim odpowiem na, muszę wyjaśnić, że strajk anegdotowy trwa. Dlatego też i dzisiaj nie będzie żadnej anegdoty. Gorzej: nie będzie żadnych anegdot, dopóki Skrypciarska Redaktorka nie otrzyma tylu e-maili z protestami od czytelników, że ulegnie i spełni wszystkie nasze żądania. Jakie to były żądania, już nie pamiętam, ale na pewno pamiętają oburzeni czytelnicy.
Tak więc – patrz, Redaktorko, jak wszyscy przez ciebie cierpią – przejdźmy do dzieła. RE ma folder zawierający listę plików zbliżoną do poniższej:
8901 George.txt
File 1234 George.txt
File 2345 George.txt
File 3456 George.txt
File 4567 George.txt
File 5678 George.txt
File 6789 George.txt
File 7890.txt
Jak widać, większość nazw plików zaczyna się słowem File i kończy słowem George; niektóre zaczynają się na File, ale nie kończą na George, inne natomiast kończą się na George, ale nie zaczynają na File. Jednak wszystkie pliki mają unikatowy element w środku, np. w pliku File 1234 George.txt jest to 1234. RE chce zachować ten środkowy element, usuwając słowa File i George, co powinno dać taką listę:
8901.txt
1234.txt
2345.txt
3456.txt
4567.txt
5678.txt
6789.txt
7890.txt
Jak to zrobić? Ano tak, na przykład:
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colFiles = objWMIService.ExecQuery _
("ASSOCIATORS OF {Win32_Directory.Name='C:\Test'} Where " _
& "ResultClass = CIM_DataFile")
For Each objFile In colFiles
strPath = objFile.Drive & objFile.Path
strExtension = objFile.Extension
strFileName = objFile.FileName
If Left(strFileName, 5) = "File " Then
intLength = Len(strFileName)
strFileName = Right(strFileName, intLength - 5)
End If
If Right(strFileName, 7) = " George" Then
intLength = Len(strFileName)
strFileName = Left(strFileName, intLength - 7)
End If
strNewName = strPath & strFileName & "." & strExtension
errResult = objFile.Rename(strNewName)
Next
Szczerze mówiąc, trafia do nas sporo pytań tego rodzaju, dotyczących usuwania fragmentów tekstu znajdujących się na początku albo końcu nazw plików. Dlatego też, a także ze względu na to, że za to nam właśnie płacą, przyjrzyjmy się temu skryptowi bliżej i spróbujmy się zorientować, co się w nim dzieje.
Skrypt rozpoczyna działanie od połączenia z usługą WMI na komputerze lokalnym. Czy możemy zmodyfikować skrypt tak, aby wykonywał to samo zadanie na zdalnym komputerze? Jasne, że tak. Wystarczy przypisać nazwę komputera zdalnego do zmiennej strComputer:
strComputer = "atl-fs-01"
Po połączeniu z usługą WMI używamy poniższego fragmentu kodu, by zwrócić kolekcję wszystkich plików (wystąpień klasy CIM_DataFile) znajdujących się w folderze C:\Test:
Set colFiles = objWMIService.ExecQuery _
("ASSOCIATORS OF {Win32_Directory.Name='C:\Test'} Where " _
& "ResultClass = CIM_DataFile")
Po zwróceniu kolekcji możemy uruchomić pętlę For Each, która przejdzie przez wszystkie znajdujące się w niej pliki. Potem możemy przejść do rzeczy.
Przyznajemy, że istnieje kilka sposobów wykonania tego zadania. Zdecydowaliśmy się na podejście wymagające kilku dodatkowych wierszy kodu, ale bezpieczniejsze w użyciu. Co sprawia, że jest ono bezpieczniejsze? Otóż na przykład moglibyśmy użyć funkcji Replace i zastąpić wszystkie wystąpienia docelowych ciągów znaków File i George w ścieżkach plików. Dlaczego tego nie zrobimy? Załóżmy, że mamy plik zatytułowany File George Washington File George.txt. Wykonanie prostej operacji wyszukania i zastąpienia dałoby nam taki plik:
Washington.txt
Innymi słowy, usunęlibyśmy nie tylko początek i koniec. To z kolei mogłoby spowodować konflikty nazw, gdyby katalog zawierał jeszcze np. plik File Washington George.txt. Wyobraźmy sobie jeszcze, że folder, w którym znajdują się interesujące nas pliki nazywa się Documents From George. Usunięcie wszystkich wystąpień słowa George zadziałałoby też w stosunku do nazwy folderu, a to spowodowałoby najróżniejsze kłopoty. A kłopotów chcemy unikać, szczególnie teraz, kiedy zależy nam na poparciu społecznym w sporze z wszechpotężną, złowrogą Redaktorką.
Tak czy inaczej, w pętli uruchamiamy następujące trzy wiersze kodu:
strPath = objFile.Drive & objFile.Path
strExtension = objFile.Extension
strFileName = objFile.FileName
Pobieramy tu po prostu różne elementy ścieżki pliku. Jeśli mamy plik o nazwie C:\Test\File 1234 George.txt, naszym zmiennym przypisane zostaną następujące wartości:
Zmienna | Wartość |
---|---|
strPath | C:\Test| |
strExtension | txt |
strFileName | File 1234 George |
Więcej informacji o właściwościach typu Drive i Path można znaleźć w przewodniku Microsoft Windows 2000 Scripting Guide (j.ang.).
Kolejnym krokiem jest określenie, czy nazwa pliku zaczyna się ciągiem znaków File oraz ewentualne usunięcie tego ciągu. Służy do tego następujący blok kodu:
If Left(strFileName, 5) = "File " Then
intLength = Len(strFileName)
strFileName = Right(strFileName, intLength - 5)
End If
Jak widać, używamy funkcji Left do określenia, czy pięć początkowych znaków w nazwie naszego pliku to File (zwróćmy uwagę na spację na końcu). Załóżmy, że tak. W takim razie używamy funkcji Len do określenia liczby znaków w ciągu (tzn. jego długości) i zachowujemy tę wartość w zmiennej intLength:
intLength = Len(strFileName)
Dochodzimy w ten sposób do poniższego wiersza kodu:
strFileName = Right(strFileName, intLength - 5)
Usuwamy tu słowo File z początku nazwy pliku. Używamy tu funkcji Right do pobrania znaków z końca ciągu i poruszamy się w kierunku. Ile znaków zamierzamy pobrać? Otóż wszystkie minus 5. Będziemy dzięki temu mieć całą nazwę pliku bez pierwszych pięciu znaków. Innymi słowy, jeśli nasz plik nazywał się File 1234 George, właściwość strFileName przyjmie następującą wartość:
1234 George
Co znaczy, że jesteśmy dokładnie w połowie drogi.
Następnie wykonujemy podobną procedurę, by sprawdzić, czy słowo George (ponownie należy pamiętać o spacji, tym razem przed samym słowem) pojawia się na końcu pliku. Jeśli tak, to usuwamy je. Służy do tego poniższy blok kodu:
If Right(strFileName, 7) = " George" Then
intLength = Len(strFileName)
strFileName = Left(strFileName, intLength - 7)
End If
Jaki będzie ostateczny wynik? Otóż właściwość strFileName będzie miała wartość składającą się tylko ze środkowej części pierwotnej nazwy:
1234
Świetnie się składa, bo właśnie o to nam chodziło. Pozostaje jednak pewien problem: używając WMI nie można zmienić nazwy pliku, o ile do metody Rename nie przekaże się kompletnej ścieżki. (Co oznacza, że sama nazwa 1234 nam wcale nie wystarcza.) Dlatego też w skrypcie mamy poniższy wiersz kodu, tworzący nową ścieżkę pliku i przechowujący tę wartość w zmiennej strNewName:
strNewName = strPath & strFileName & "." & strExtension
Nie ma tu nic szczególnie złożonego. Łączymy po prostu poniższe wartości:
- C:\Test\
- 1234
- .
- txt
Ich połączenie sprawi, że właściwość strNewName uzyska taką wartość:
C:\Test\1234.txt
I wiecie co? Macie rację! Wartość ta niepokojąco przypomina pełną ścieżkę pliku! Możemy teraz wywołać metodę Rename i zmienić nazwę:
errResult = objFile.Rename(strNewName)
Teraz możemy powrócić na początek pętli i powtórzyć ten proces dla kolejnego pliku w kolekcji. Po zakończeniu działania skryptu, folder C:\Test będzie zawierać następujący zestaw plików:
8901.txt
1234.txt
2345.txt
3456.txt
4567.txt
5678.txt
6789.txt
7890.txt
Zupełnie nieźle, no nie?
Do początku strony |