PowerShell - Odczytywanie części nazwy pliku

PowerShell - Odczytywanie części nazwy pliku
Animusz_
  • Rejestracja:ponad 11 lat
  • Ostatnio:5 miesięcy
  • Postów:32
0

Witam,
Piszę skrypt w PowerShellu do obsługi logów (można założyć że zwykłe pliki *.txt w danym folderze) i chciałbym wyselekcjonować te nazwy plików w tym folderze względem dzisiejszej daty (to zrobione). Moim wynikiem są nazwy logów z dnia: dziś. Mając tę informację chciałbym nazwy plików wyselekcjonować otrzymując tylko te, które zawierają ostatnie pięć znaków np. "th.txt".
Przykładowo mam wynik logów z dnia: dziś:

Kopiuj
log1-222.txt
log2-333.txt
log3-th.txt
log5-322th.txt
log9-333th.tx

I chciałbym uzyskać z kolejnej modyfikacji algorytmu:

Kopiuj
log3-th.txt
log5-322th.txt
log9-333th.txt

Przeszukałem wiele stron na ten temat i próba stosowania dot-netowych metod do wycinania fragmentów z tekstu nie działała w FOREACH. Nie chcę tego robić w C++ czy C# bo zależy mi na skrypcie gdyż można go szybko edytować i przejrzeć jego strukturę bez uruchamiania środowiska.
Mój algorytm:

Kopiuj
$todayData = get-date
$nameOfFile= Get-ChildItem 'E:\Logi' -Filter *.txt | `
where {$_.lastWritetime.month -eq $todayData.month -AND $_.lastWritetime.day -eq $todayData.day -AND $_.lastWritetime.year -eq $todayData.year } | `
format-Table Name
$nameOfFile

To daje w wyniku nazwy plików z dzisiejszego dnia. Pomysły miałem różne i nie wychodziły, np:

Kopiuj
$todayData = get-date
$nameOfFile= Get-ChildItem 'E:\Logi' -Filter *.txt | `
where {$_.lastWritetime.month -eq $todayData.month -AND $_.lastWritetime.day -eq $todayData.day -AND $_.lastWritetime.year -eq $todayData.year } | `
format-Table Name
$nameOfFile
foreach($item in $nameOfFile)
{
if($item.EndsWith("th.txt"))
{
$item
}
}

Ale żadnych metod nie mogę używać w pętli 'foreach'. Wynik kończy się błędami typu:

Kopiuj
Method invocation failed because [Microsoft.PowerShell.Commands.Internal.Format.GroupStartData] doesn't contain a method named 'EndsWith'.
At G:\SecondProject\dateOfFile.ps1:8 char:18
+ if($item.EndsWith <<<< ("th.txt"))
    + CategoryInfo          : InvalidOperation: (EndsWith:String) [], RuntimeException
    + FullyQualifiedErrorId : MethodNotFound

Użycie przed pętlą tej samej metody na sztywnej zmiennej tak jak:

Kopiuj
 $nazwa="blablath.txt"
$nazwa.EndsWith("th.txt")

Da wynik true.
Jak mogę to zrobić na wynikowych nazwach plików ?
Jeszcze z ciekawszych pomysłów to:
([string]$item).EndsWith("th.txt"))
Ale fragment "[string]" nie jest równoważny z rzutowaniem typu ? Bo wynik był oczywiście false z powodu takiego, że
[string]$item daje w wyniku Microsoft.PowerShell.Commands.Internal.Format.FormatStartData
Ale nie korzystając z rzutowania i pisząc $item.toString() otrzymuje ten sam wynik co rzutując. ^^

Może ktoś mi pomóc jak się uporać z tym?

edytowany 2x, ostatnio: Animusz_
Animusz_
  • Rejestracja:ponad 11 lat
  • Ostatnio:5 miesięcy
  • Postów:32
1

Widzę że mamy tu ekspertów w tej dziedzinie ;D No nic, rozwiązałem ten problem wykonując rzutowanie w miejscu inicjacji, bo każdy przechwycony obiekt ma typ 'obiekt' z tego co się domyśliłem, dlatego nie mogłem używać "substring(x,y)" ani tablicowych indeksów [] do wydobywania znaków. Jak to rozwiązałem?
Błędny przykład: (wygeneruje błąd w ostatniej linii)

Kopiuj
$nameOfFile= Get-ChildItem 'E:\Logi' -Filter *.txt | `
where {$_.lastWritetime.month -eq $todayData.month -AND $_.lastWritetime.day -eq $todayData.day -AND $_.lastWritetime.year -eq $todayData.year } | `
format-Table Name
($nameOfFile[0]).substr(0,1)

Poprawiony przykład:

Kopiuj
[string]$nameOfFile= Get-ChildItem 'E:\Logi' -Filter *.txt | `
where {$_.lastWritetime.month -eq $todayData.month -AND $_.lastWritetime.day -eq $todayData.day -AND $_.lastWritetime.year -eq $todayData.year } | `
format-Table Name
($nameOfFile[0]).substr(0,1)

Wnioski:
Jeśli chcesz posługiwać się metodami "stringowymi" przy pierwszym użyciu zmiennej "$zmienna" zastosuj rzutowanie [string]. Np. [string]$zmienna ... w moim rozumieniu daje to taki wynik jak w C#/C++ "string zmienna="" "
Wklejam do dla przyszłych google'owiczów i skrypciarzy ^^

edytowany 2x, ostatnio: Animusz_
madmike
Eksperci też mają wakacje czasem ;)
DU
Get-ChildItem w zasadziemoperuje na kolekcji i zwraca Fileainfo. Format-Table natomiast formatuje wyniki i obudowuje obiekty wraperem. stad byl problem w petli a zutowanie na string pomoglo... powershell traktuaje kolekcje jednolementowa jako ten obiekt. Sprawdze to przy dostepie do konsoli PS da sie tu posprztac. Przy okazji forum .NET moze miec wiecej eksperow z PS wkoncu to hula wlasnie na tym frameworku
madmike
@dubcio, odpowiedzi piszemy w poście, komentarze do takich luźnych uwag...
DU
  • Rejestracja:ponad 11 lat
  • Ostatnio:ponad 11 lat
  • Postów:25
2

Obiecany skrypt:

Kopiuj
$path = ".\"
# Get-Date zwraca obiekt DateTime on ma właściwość Date, ktora też jest typu DateTime ale z czasem usatwionym na 00:00:00
$date = (Get-Date).Date

# filtruje pliki do zmiennej
$files = Get-ChildItem -Path $path -Filter "*th.txt" | # według wzorca, gwiazdek może być wiecej
    where {$_.LastWriteTime.Date -eq $date} # porównanie samych daty, LastWriteTime to też typ DateTime

'formatowanie listy jako tablicy'
$files | Format-Table

'formatowanie listy jako liste własściwości'
$files | Format-List


'typy: $files'
$files.GetType() # files jest talicą obiektów...
$files[0].GetType() # ...typu IO.FileSystemInfo

'typy: $files | Format-Table'
($files | Format-Table).GetType() # files jest talicą obiektów...
($files | Format-Table)[0].GetType() # ...typu Microsoft.PowerShell.Commands.Internal.Format.StartData


'iterowanie po elementach listy'
$files | foreach {
    $_.GetType() # każdy jest typu IO.FileSystemInfo
    $_.Name # sama nazwa pliku
    $_.FullName # pełna ścieżka
    "$_" # "wklejenie" do tekstu
    [String]$_ # rzutowanie na String 
}

W twoim przykładzie tablicę FileSystemInfo zamieniałeś operacją w strumieniu | Format-Table na obudowę formatującą wyniki. Do przykładu dodałem też inny formater.

Jeżeli czaiłbyś wybrać w jednym strumieniu tylko nazwy plików to do tego służy polecenie select:

Kopiuj
$files = Get-ChildItem -Path $path -Filter "*th.txt" |
    where {$_.LastWriteTime.Date -eq $date} |
    select -ExpandProperty Name # wybieram tylko nazwe pliku

'typy z expand property: $files'
$files.GetType() # files jest talicą obiektów...
$files[0].GetType() # ...typu String

'iterowanie po elementach listy'
$files | foreach {
    $_.GetType() # każdy jest typu String (choć mówi że object ;)
    $_ # sama nazwa pliku
}

Mimo iż PowerShell jest językiem skryptowym (dynamicznym...w znacznym stopniu też) to jednak pod maską używa .NET frameworka i jego systemu typów. Można więc szukać w MSDN informacji o funkcjach czy własnościowy obiektów np. DateTime - http://msdn.microsoft.com/en-us/library/system.datetime.aspx.

Jeszcze warto nadmienić, że w PS można używać skrótów do typów. Dokładnie pomijać przestrzeń System (np. [String]$_ jest równoważne z [System.String]$_</code>. I jeszcze jedna fajna możliwość w PS to parsowanie stringów <code>[DateTime]"2013-08-23" daje nam datę i czas w typach .NET.

Przy okazji polecam narzędzie PowerGUI (http://www.powergui.org/downloads.jspa). Jest nieco ciężkie (doży rozmiar pliku, czas ładowania) ale za to jest dopełnianie poleceń i ich argumentów, lepsze debugowanie od domyślnego narzędzia i podgląd zmiennych. Ponadto potrafi dopełniać właściwości i funkcje jeżeli zmienna posiada już jakaś wartość.

edytowany 1x, ostatnio: dubcio
Animusz_
  • Rejestracja:ponad 11 lat
  • Ostatnio:5 miesięcy
  • Postów:32
1

Dzięki za wyczerpującą odpowiedź, wiedzy nigdy nie ma za mało ;) Ludzie z Windowsem 7 (lub nowszym) mają wbudowane GUI, może mniej zaawansowane ale w pełni samodokumentowany i przy użyciu głowy i znajomości angielskiego można sobie poradzić ;) Najlepszy informatyk to leniwy informatyk, nie każdy chce pobierać coś hah, ale dzięki za poświęcenie czasu :)

Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)