Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien
Toon posts:

powershell metadata van bestanden in submappen bekomen

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ik wil graag een inventaris maken van mijn muziekcollectie met behulp van Powershell, m.a.w. bepaalde metadata-tags van die bestanden naar een .txt-bestand schrijven. Mijn collectie zit in een soort mapstructuur, in een (vergeefse) poging het overzichtelijk te houden. Ook staan er ook nog wat .mp3-tjes los in de hoofdmap zelf. De bedoeling is dus het oplijsten van alle niet-mapelementen uit de hoofdmap, dus inclusief die in de submappen. Bij het testen (het naar het scherm schrijven i.p.v. naar de txt) blijkt dat de .mp3-tjes in de hoofdmap worden opgelijst zoals de bedoeling is, maar de submappen van de hoofdmap niet worden doorzocht. De mappen zelf vindt hij wel. Hieronder vindt u mijn eerste poging:

#//////////////////////////////////////////////////////////////////////////////////
$map = "C:\Users\Ik\Music\muziek"
function lijstopties(){

foreach($submap in $map){

$objShell = New-Object -ComObject Shell.Application
$objMap = $objShell.namespace($subMap)
foreach ($bestand in $objMap.items()){

for ($a=0 ; $a -le 266; $a++){

$objMap.getDetailsOf($bestand, $a)
}
}
}
}
lijstopties
#/////////////////////////////////////////////////////////////////////////////////////

Zoals hierboven gezegd faalt dit jammerlijk: "foreach($submap in $map)" was een beetje wishful thinking, en geeft enkel $map terug, $map is immers een string. Dat is de reden waarom alleen de hoofdmap wordt doorzocht, namespace wordt alleen voor de hoofdmap veranderd.
Wat googlen leert dat

$items = Get-ChildItem -Recurse "C:\Users\Ik\Music\muziek"| where {$_.psiscontainer -ne $true}

wel doet wat ik wil, en veel simpeler is dan het gepruts met de lussen.
Probleem is nu, ik kan op vb. het 6de element uit $items niet meer "$objMap.getDetailsOf($items[5], $a)" toepassen om de metadata te bekomen. Powershell ziet dit blijkbaar als een variant op "$objMap.getDetailsOf($objMap.items(), $a)", wat de naam van het metadatadeel geeft.

vb: $objMap.getDetailsOf($items[5], 0)

zal "Name" geven, terwijl ik die "Name" ingevuld wil zien door de naam van het bestand.
Na nog wat gegoogle en geprobeer dacht ik te mogen besluiten dat getdetailsof() als eerste parameter een system.marshalbyrefobject wil, terwijl alle $items[i] system.io.fileinfo blijken te zijn, een subklasse van system.marshalbyrefobject. Ik had gehoopt via de methode MemberwiseClone(true) van system.io.fileinfo de bijhorende system.marshalbyrefobject te kunnen vinden.
Een of meerdere elementen in die redenering kloppen blijkbaar niet, want:

($items[1]).MemberWiseClone().gettype()

geeft:

Method invocation failed because [System.IO.FileInfo] doesn't contain a method named 'MemberWiseClone'.
At I:\rest\powershell\Untitled1.ps1:8 char:28
+ ($items[1]).MemberWiseClone <<<< ().gettype()
+ CategoryInfo : InvalidOperation: (MemberWiseClone:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound

Mijn vraag is dus: hoe kan ik system.io.fileinfo "casten" (is eigenlijk het goede woord niet) naar system.marshalbyrefobject? Of beter, hoe verkrijg ik het system.marshalbyrefobject waarvan $items[5] de
system.io.fileinfo is?

Oja, de reden waarom ik niet gewoon vb:

$items = Get-ChildItem -Recurse "C:\Users\Ik\Music\muziek"| where {$_.psiscontainer -ne $true}|select Name

gebruik, is omdat je volgens mij bij select "hard" moet coderen wat je wil dat geselecteerd wordt (na elkaar pipelinen gaat natuurlijk niet). Mijn uiteindelijke doel is een gebruiker te laten ingeven (door middel van getallen) welke metadata hij wil. Dan moet ik gewoon getdetailsof() voor die getallen oproepen, en is er niks hard te coderen.

Het enige waar ik dus aan vast zou willen houden is het gebruik van dat getdetailsof(), tenzij ook daarvoor een betere oplossing bestaat natuurlijk (bij gebruikersinput).

Dank u wel!

  • alt-92
  • Registratie: Maart 2000
  • Niet online

alt-92

ye olde farte

Hoezo zou je niet verder kunnen pipen?

[ Voor 79% gewijzigd door alt-92 op 07-09-2011 16:50 ]

ik heb een 864 GB floppydrive! - certified prutser - the social skills of a thermonuclear device


Verwijderd

Topicstarter
ik ben nog niet zo vertrouwd met powershell, maar zoals ik het select-ding begrijp selecteert het enkele eigenschappen van wat er in de pipline komt, en geeft enkel die terug. als ik bijvoorbeeld zowel de naam als de grootte wil, dan kan ik wel

$items = Get-ChildItem -Recurse "C:\Users\Ik\Music\muziek"| where {$_.psiscontainer -ne $true}|select Name, Size

doen, maar niet

$items = Get-ChildItem -Recurse "C:\Users\Ik\Music\muziek"| where {$_.psiscontainer -ne $true}|select Name|select Size

omdat dat volgens mij het size-attribuut van de strings in de Name-array geeft. zo'n string heeft geen size-attribuut, en dus krijg ik een lege lijst terug. ik heb dit getest, en ik krijg inderdaad een lege lijst terug. of de redenering hierboven juist is weet ik niet, maar het resultaat klopt wel.

dus, stel dat de gebuiker wil dat hij de naam en de grootte van het bestand wil, moet ik iets kunnen hebben van de vorm

$items = Get-ChildItem -Recurse "C:\Users\Ik\Music\muziek"| where {$_.psiscontainer -ne $true}|select ??????

waarbij ???? een variabele is die ik kan instellen op wat de gebruiker wil. ik heb het met een string geprobeerd:

$naam="Name"
$items = Get-ChildItem -Recurse "C:\Users\Ik\Music\muziek"| where {$_.psiscontainer -ne $true}|select $naam
$items

dit werkt inderdaad perfect, maar:

$naam="Name,Size"
$items = Get-ChildItem -Recurse "C:\Users\Ik\Music\muziek"| where {$_.psiscontainer -ne $true}|select $naam
$items

geeft een lege lijst omdat (denk ik) powershell zoekt naar een attribuut "Name,Size" , wat niet bestaat, i.p.v. door te hebben dat ik twee verschillende attributen wil.
komt daar nog bij dat, als ik het inderdaad op deze manier zou doen, ik ofwel een gigantische rij if-elsen nodig heb (266 om precies te zijn), ofwel een onbekend soort ????-variabelen in een lijst moet stoppen, een soort waar ik persoonlijk niet van denk dat ze bestaan.
dus is opnieuw pipelinen (dit is denk ik waar u naar toe wilde?):

$items1 = Get-ChildItem -Recurse "C:\Users\Ik\Music\muziek"| where {$_.psiscontainer -ne $true}|select Name
$items2 = Get-ChildItem -Recurse "C:\Users\Ik\Music\muziek"| where {$_.psiscontainer -ne $true}|select Size

resulterende in twee lijsten met info die ik wil (denk ik, want ik geloof dat op deze manier zelfs niet alle metadata beschikbaar zijn die via getdetailsof wel kunnen). maar dan heb ik hetzelfde probleem: ofwel 266 if-elsen ofwel een teller met een lijst ????-variabelen...

ik denk dat het veel makkelijker is om gewoon die getalletjes in een rij steken en daar getdetailsof op los te laten?

maar daarmee is mijn probleem niet opgelost natuurlijk ;)

dank u voor uw moeite!