petergyger
Goto Top

Powershell: Verzeichnis ohne Datei x

Hallo

Ausgangslage
Verzeichnis mit 2 Unterverzeichnisebenen:
[root]
¦__[Leve1]
¦______[Level2]

In den Verzeichnissen von [Level2] hat es Dateien.
Ich benötige eine Liste aller Verzeichnisse, welche die Datei "weekday.xml" nicht enthalten.

Entwurf
Get-ChildItem -Path "t:\Kalender\an" -Recurse -Directory | ForEach-Object {  
    $directory = $_
    $containsFile = Get-ChildItem -Path $directory.FullName -Filter "metadata.opf" -File -ErrorAction SilentlyContinue  

    if (-not $containsFile) {
        [PSCustomObject]@{
            Directory = $directory.FullName
        }
    }
} | Format-Table

Dieser Entwurf zeigt alle Verzeichnisse der Ebene2 an. Egal ob weekday.xml vorhanden ist.
Hinweis auf meinen Denkfehler erwünscht...

Beste Grüsse

Content-Key: 7886732637

Url: https://administrator.de/contentid/7886732637

Printed on: December 6, 2023 at 04:12 o'clock

Member: Kraemer
Solution Kraemer Jul 18, 2023 updated at 10:49:24 (UTC)
Goto Top
Moin,

Test-Path ist dein Freund.

Gruß
Mitglied: 6376382705
Solution 6376382705 Jul 18, 2023 updated at 10:49:24 (UTC)
Goto Top
Hi.

# Gib hier den Pfad des übergeordneten Verzeichnisses ein, in dem du suchen möchtest.
$baseDirectory = "C:\Pfad\Zum\Übergeordneten\Verzeichnis"  

# Liste aller Verzeichnisse im übergeordneten Verzeichnis abrufen und nach Verzeichnissen ohne "weekday.xml" filtern. 
$directoriesWithoutWeekdayXml = Get-ChildItem -Path $baseDirectory -Directory |
    Where-Object { -Not (Test-Path (Join-Path $_.FullName "weekday.xml")) }  

# Die Liste der Verzeichnisse ohne "weekday.xml" ausgeben. 
$directoriesWithoutWeekdayXml | ForEach-Object { $_.FullName }

ungetestet.

Gruß
Member: PeterGyger
PeterGyger Jul 18, 2023 updated at 10:49:24 (UTC)
Goto Top

# Gib hier den Pfad des übergeordneten Verzeichnisses ein, in dem du suchen möchtest.
$baseDirectory = "C:\Pfad\Zum\Übergeordneten\Verzeichnis"  

# Liste aller Verzeichnisse im übergeordneten Verzeichnis abrufen und nach Verzeichnissen ohne "weekday.xml" filtern. 
$directoriesWithoutWeekdayXml = Get-ChildItem -Path $baseDirectory -Directory |
    Where-Object { -Not (Test-Path (Join-Path $_.FullName "weekday.xml")) }  

# Die Liste der Verzeichnisse ohne "weekday.xml" ausgeben. 
$directoriesWithoutWeekdayXml | ForEach-Object { $_.FullName }

Hallo emm386

Erster Test mit Deinem Snippet durchgelaufen. Sieht gut aus. Wenn ich noch Fehler finde, dokumentiere ich das hier.
Einen extra Punkt für die ausführliche Dokumentation.

Beste Grüsse



Test-Path ist dein Freund.

Gruß
Hallo erik

Exakt. Das war mir entfallen.

Beste Grüsse
Mitglied: 7426148943
7426148943 Jul 18, 2023 updated at 10:56:55 (UTC)
Goto Top
Moin.
Es geht auch ohne Test-Path
$baseDirectory = "C:\Pfad\Zum\Übergeordneten\Verzeichnis"   
Get-ChildItem $baseDirectory -Directory | ?{!$_.GetFiles("weekday.xml")} | select -Expand Fullname  

Zeppel
Member: PeterGyger
PeterGyger Jul 18, 2023 at 10:58:37 (UTC)
Goto Top
$baseDirectory = "C:\Pfad\Zum\Übergeordneten\Verzeichnis"   
Get-ChildItem $baseDirectory -Directory | ?{!$_.GetFiles("weekday.xml")} | select -Expand Fullname  

Hallo Zeppel

Das ist definitiv smart! Eine K.O. Lösung - effizienter geht es nicht - IMHO.

Aber...

Alle Lösungen haben einen Designfehler. D.h. ich habe die Aufgabe nicht klar genug geschildert.
Es sollen nur die Verzeichnisse der Ebene2 nach dieser Datei durchsucht werden.
Die Ebene1 hat nur Verzeichnisse.

Ich editiere /teste gerade die Lösung. Mal sehen, ob ich zum Ziel komme.

Beste Grüsse
Mitglied: 7426148943
Solution 7426148943 Jul 18, 2023 updated at 11:05:32 (UTC)
Goto Top
lle Lösungen haben einen Designfehler. D.h. ich habe die Aufgabe nicht klar genug geschildert.
Es sollen nur die Verzeichnisse der Ebene2 nach dieser Datei durchsucht werden.
Die Ebene1 hat nur Verzeichnisse.
In dem Fall liefert dir das hier das Gewünschte, einfach noch ein "\*\*" an die Variable pappen, feddisch.
$baseDirectory = "C:\Pfad\Zum\Übergeordneten\Verzeichnis"     
Get-ChildItem "$baseDirectory\*\*" -Directory | ?{!$_.GetFiles("weekday.xml")} | select -Expand Fullname    
Member: PeterGyger
PeterGyger Jul 18, 2023 at 11:19:29 (UTC)
Goto Top
Hallo Zeppel

Gerade 2x erfolgreich getestet. Noch dazu mit einem nano kleinen Snippet. Pokal verdient

...
Und sie laufen! Naß und nässer
wirds im Saal und auf den Stufen.
Welch entsetzliches Gewässer!
Herr und Meister! hör mich rufen! –
Ach, da kommt der Meister!
Herr, die Not ist groß!
Die ich rief, die Geister
werd ich nun nicht los.

»In die Ecke,
Besen, Besen!
Seids gewesen.
Denn als Geister
ruft euch nur zu seinem Zwecke,
erst hervor der alte Meister.«


Beste Grüsse
Mitglied: 7426148943
7426148943 Jul 18, 2023 updated at 11:25:53 (UTC)
Goto Top
Naja kürzer geht hier auch noch ist dann aber für einen Laien der das lesen muss schwer interpretierbar
(ls "$baseDirectory\*\*" -Dir | ?{!$_.GetFiles("weekday.xml")}).Fullname  
Member: PeterGyger
PeterGyger Jul 18, 2023 at 12:50:16 (UTC)
Goto Top
Hallo Zeppel

Da lerne ich wieder extrem viel über PS.

$baseDirectory = "d:\temp"       
(ls "$baseDirectory\*\*" -Dir | ?{!$_.GetFiles("weekday.xml")}).Fullname    

Analyse:
- Code in der Klammer kapselt - d.h. das Resultat wird als Ausdruck behandelt. In diesem soll das Property "Fullname" angezeigt werden, wenn der Ausdruck ein Objekt schickt.
-
ls "$baseDirectory\*\*"  
-- Erstellt eine Liste der Objekte im Dateisystem im Pfad ls "$baseDirectory\*\*"
-
-DIR 
-- jetzt wird es unlogisch. "ls" als auch "dir" sind vorgegebe Aliase von GCI (Get-Alias -Definition Get-ChildItem)
-- d.h. ich kann in der PS den Befehl
ls D:\bibliothek.bak -dir
absetzen. "-DIR" zeigt jedoch keinen Effekt. Wenn ich aber
ls D:\bibliothek.bak -ls
eingebe erhalte ich einen Fehler:
Get-ChildItem : Es wurde kein Parameter gefunden, der dem Parameternamen "ls" entspricht.  

A: Welchen Zweck hat der Parameter "-ls"? 🚧
B: Weshalb erhalte ich bei Dir einen Fehler? 🚧
C: Wenn den Parameter "-ls" weglasse, funktioniert das Skript dennoch 🤔🤔🤔

$baseDirectory = "D:\temp"       
(ls "$baseDirectory\*\*" | ?{!$_.GetFiles("weekday.xml")}).Fullname    

Pipe
-
?
-- Alias für das "where-object"
-
!
-- negiert (NOT) die nachfolgende Funktion
-
$_
-- Variable für das aktuelle Element im Durchgang
-
$_.GetFiles("weekday.xml")  
-- Zugriff auf Datei Attribute von $_
Zusammengefasst überprüft der Filter nach Pipe, ob die aktuelle Datei in der Liste kein Property mit dem Wert "weekday.xml" hat. Wenn ja, wird der Wert des Property Fullname angezeigt.

Abgesehen von den zwei Baustellen oben, verstehe ich diese Zeile.
Danke für die Lektion.

Beste Grüsse
Member: Kraemer
Kraemer Jul 18, 2023 at 13:10:25 (UTC)
Goto Top
Ich versuchs mal face-wink

 Get-Alias dir

CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Alias           dir -> Get-ChildItem

Get-Alias ls

CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Alias           ls -> Get-ChildItem

Bei dem -dir bin ich mir auch unsicher. Es ist schon mal kein Parameteralias von Get-Childitem
(Get-Command Get-ChildItem).Parameters.Values.aliases

und auch kein Alias von -Directory obwohl genau das ersetzt wurde
(Get-Command Get-ChildItem).Parameters["Directory"].Aliases  
ad
d
Mitglied: 7426148943
7426148943 Jul 18, 2023 updated at 14:50:10 (UTC)
Goto Top
Zitat von @PeterGyger:
-
-DIR 
-- jetzt wird es unlogisch. "ls" als auch "dir" sind vorgegebe Aliase von GCI (Get-Alias -Definition Get-ChildItem)
ls ist ein Alias für Get-ChildItem korrejt, aber -Dir ist ein Parameter von Get-Childitem und zwar die Abkürzung von -Directory! Das es kein Alias ist erkennst du an dem Dash vor dem Namen somit ist es ein Parameter der Funktion Get-ChildItem.

A: Welchen Zweck hat der Parameter "-ls"? 🚧
ls ist kein Parameter sonder ein Alias von Get-ChildItem.
B: Weshalb erhalte ich bei Dir einen Fehler? 🚧
C: Wenn den Parameter "-ls" weglasse, funktioniert das Skript dennoch 🤔🤔🤔
Du wirfst CMDLet(bzw. Alias) und Parameter durcheinander ganz einfach.
Es gibt Funktionen (CMDLets) diese lassen sich mit Aliasen aufrufen sofern angelegt , die Funktionen selbst haben Parameter die mit dem Dash(-) eingeleitet werden, aber auch unbenannte Parameter haben können die man direkt angeben kann wie hier bspw. der Pfad. Für die Parameternamen selbst gibt es ebenfalls Abkürzungen wie das -Dir hier bspw. Die Abkürzung von -Directory ist.
Nun klar?

Wenn nicht hier zum nachlesen
https://learn.microsoft.com/en-us/powershell/scripting/developer/cmdlet/ ...

Vielleicht mal von der Pike auf lernen, an einem verregneten Wochenende hat man das durch ...

Powershell Leitfaden für Anfänger
Member: PeterGyger
PeterGyger Jul 19, 2023 at 15:05:24 (UTC)
Goto Top
Hallo 7426148943

Punkt "-dir"
Das habe ich inzwischen über SS64.com herausgefunden.
Da Du diese Info fett hervorgehoben hast, hast Du Dich wahrscheinlich genervt. Mein Glück, dass es auch anderen Teilnehmern wie Kraemer nicht klar war...

Punkt "-ls"
Das habe ich bereits früher festgehalten.
ps-dir

Das Du nicht nachvollziehen kannst, dass wenn man links "ls" liest und rechts "-Dir" sieht, automatisch an den Alias denkt, ist schade. In der Psychologie nennt man das einen Anker Effekt. Zu diesen Basiskenntnissen kann ich Dir gerne ein Buch empfehlen.

Was sagt ein Profi wie Du zu diesem Konstrukt?
"$baseDirectory\*\*"

Die Bücher die ich über PS als OO Sprache gelesen habe, müsste man jede Verzeichnisebene als Objekte einlesen. Und am Schluss die Funktion einsetzen. Nur weil es "geht", heisst es ja nicht das es ein guter bzw. effizienter Stil ist.
Auch als Praktiker bin ich offen für strategische Konzepte einer Sprache.

Beste Grüsse