2017-08-07 4 views
2

Maintenant, avant de jeter la réponse super simple de Get-ChildItem -Recurse, voici ma question unique:Comment RECURSE à travers une arborescence de répertoires pour trouver des fichiers avec Powershell

Je me connecte à distance à Azure avec Powershell , en saisissant la liste du site (emplacement), puis en faisant une boucle sur les sites et en trouvant toutes les images dans la structure du répertoire, en utilisant l'API Kudu. Puisque Kudu n'a aucune notion de récursivité, je dois construire ma propre fonction récursive pour récupérer toutes les images du répertoire racine, puis recurse à travers tous les enfants et enfants de chidren, etc., pour trouver aussi les fichiers image dans ces répertoires.

Voici mon code pour se connecter à Azure et saisir le répertoire racine:

function Get-AzureRmWebAppPublishingCredentials($resourceGroupName, $webAppName, $slotName = $null){ 
    if ([string]::IsNullOrWhiteSpace($slotName)){ 
     $resourceType = "Microsoft.Web/sites/config" 
     $resourceName = "$webAppName/publishingcredentials" 
    } 
    else{ 
     $resourceType = "Microsoft.Web/sites/slots/config" 
     $resourceName = "$webAppName/$slotName/publishingcredentials" 
    } 
    $publishingCredentials = Invoke-AzureRmResourceAction -ResourceGroupName $resourceGroupName -ResourceType $resourceType -ResourceName $resourceName -Action list -ApiVersion 2015-08-01 -Force 
     return $publishingCredentials 
} 


function Get-KuduApiAuthorisationHeaderValue($resourceGroupName, $webAppName, $slotName = $null){ 
    $publishingCredentials = Get-AzureRmWebAppPublishingCredentials $resourceGroupName $webAppName $slotName 
    return ("Basic {0}" -f [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $publishingCredentials.Properties.PublishingUserName, $publishingCredentials.Properties.PublishingPassword)))) 
} 

function Fill-MimeTypes(){ 
    return @("image/gif", "image/x-icon", "image/jpeg", "image/png", "image/tiff", "image/bmp") 
} 

$MimeTypes = Fill-MimeTypes 
[System.Collections.ArrayList]$Directories = @() 


#Login to Azure Account 
Login-AzureRmAccount 

#Get the Azure subscription 
Select-AzureRmSubscription -SubscriptionName [Subscription Name] 

#Get the resource group name 
$resourceGroupName = [Resource Group Name] 

#Get the WebApp name 
$Resources = Find-AzureRmResource -ResourceType Microsoft.Web/sites -ResourceGroupNameContains $resourceGroupName 

ForEach($Resource in $Resources) 
{ 
    #Get the WebAppName 
    $WebAppName = $Resource.Name 

    #Now, get the publishing creds 
    $publishingCredentialsHeader = Get-KuduApiAuthorisationHeaderValue $resourceGroupName $WebAppName $null 
    $ApiUrl = "https://$WebAppName.scm.azurewebsites.net/api/vfs/site/wwwroot/" 

    #Now get the list of files in the wwwroot directory 
    $InitialList = Invoke-RestMethod -Uri $ApiUrl -Headers @{Authorization=$publishingCredentialsHeader} -Method GET -ContentType "application/json" 

    ForEach($Item in $InitialList) 
    { 
     If($MimeTypes -Contains $Item.mime)  
     { 
      #Add image file data to a collection 
     } 

     If ($Item.mime -eq "inode/directory") 
     { 
      #So, here is where I need to recurse... 
      #The mime type of inode/directory means it's a directory ;) 
      #I now need to call the Api again with the Url and get the contents of the current directory and rinse and repeat until done 
      #But I cannot forget about the other directories in the root directory and their children. 
     } 
    } 
} 

Comment puis-je écrire la fonction récursive?

+1

Jusqu'à un .. Intéressé à faire cela sans Get-ChildItem. Une fonction personnalisée peut avoir des paramètres supplémentaires qui seraient très utiles dans la bonne situation – cet51

+1

Vous avez démontré que vous savez écrire et appeler des fonctions, et vous avez écrit dans les commentaires ce que vous devez faire - "* # Ajouter un fichier image données à une collection * "- Je suppose que vous savez comment faire ce bit? "* # Je dois maintenant rappeler l'Api avec l'Url *" - et ce bit? Alors, votre question est-elle vraiment "expliquez-vous la récursivité?" Il existe un certain nombre d'exemples de chemins de répertoire récursifs dans différentes langues - https://stackoverflow.com/q/24783862/478656 ou https://rosettacode.org/wiki/Walk_a_directory/Recursively - qui exécutent le modèle de marche récursive dans un sens ou un autre – TessellatingHeckler

+1

et le motif est plus ou moins ce que vous avez écrit dans vos commentaires, par exemple function Recursive-Walk {Ajouter des fichiers à la collection; Pour chaque répertoire: Recursive-Walk $ directory}; "* Je ne peux pas oublier les autres répertoires dans le répertoire racine *" - vous ne pouvez pas les oublier, ils sont maintenus dans la structure du code courant de la même manière que '1..10 | foreach {numéro-de-processus $ _} 'n'oublie pas les numéros quand il est envoyé à un appel de fonction – TessellatingHeckler

Répondre

2

Je l'écrirais comme suit. Certains est psuedo code comme je ne suis pas versé dans la syntaxe PS ou mots-clés:

function Collect-Files($apiUrl, $creds, $currentDir) 
{ 
    $list = Invoke-RestMethod -Uri $apiUrl/$currentDir/ -Headers @{Authorization=$creds} -Method GET -ContentType "application/json" 

    If($MATCHLIST -eq $null) 
    { 
     $MATCHLIST = @() #initialize array 
    } 


    ForEach($Item in $list) 
    { 
     If($MimeTypes -Contains $Item.mime)  
     { 
      #Add image file data to a collection 
      $MATCHLIST += $Item #add to array 
     } 

     If ($Item.mime -eq "inode/directory") 
     { 
      $nextDir = $Item.name 
      $MATCHLIST = Collect-Files $apiUrl $creds $currentDir/$nextDir 
     } 
    } 

    return ($MATCHLIST) 
} 

Ensuite, votre code précédent appelleraient cette fonction comme suit:

#Get the WebApp name 
$Resources = Find-AzureRmResource -ResourceType Microsoft.Web/sites -ResourceGroupNameContains "Nav-Inventory" 

ForEach($Resource in $Resources) 
{ 
    #Get the WebAppName 
    $WebAppName = $Resource.Name 

    #Now, get the publishing creds 
    $publishingCredentialsHeader = Get-KuduApiAuthorisationHeaderValue $resourceGroupName $WebAppName $null 
    $ApiUrl = "https://$WebAppName.scm.azurewebsites.net/api/vfs/site/" 

    #Now get the list of files in the wwwroot directory 
    $InitialList = Invoke-RestMethod -Uri $ApiUrl -Headers @{Authorization=$publishingCredentialsHeader} -Method GET -ContentType "application/json" 

    $MATCHES += Collect-Files $ApiUrl $publishingCredentialsHeader "wwwroot" 
} 

récursion de base.

+0

J'ai mis à jour votre code pour le code de travail réel pour la postérité et les futurs lecteurs. – crackedcornjimmy