1 votes

Windows - copie de fichiers en fonction de l'existence d'autres fichiers

J'ai un dossier avec des sous-dossiers de photos au format jpg. Les fichiers sont organisés comme suit:

Z:\jpgs\Armouries\fb\IMG_1286.jpg
Z:\jpgs\Balloon\fb\IMG_1129.jpg
Z:\jpgs\Party\fb\P5060092.jpg

etc... Il y a quelques centaines de ces fichiers.

J'ai aussi un autre dossier avec des sous-dossiers comme suit:

z:\masters\Armouries\IMG_1286.RAW
z:\masters\Balloon\IMG_1129.DNG
z:\masters\Party\P5060092.CR2

etc... Encore une fois, il y a plusieurs centaines de ces dossiers.

Ce que je veux faire, c'est copier les fichiers de l'arborescence 'masters' dans un nouveau dossier UNIQUEMENT si le même nom de fichier existe dans l'arborescence 'jpgs'. Tous les fichiers dans l'arborescence masters n'ont pas de jpg correspondant - ces fichiers seraient ignorés.

J'espère avoir expliqué cela clairement ... des indications ?

2voto

root Points 3412
$jpgs = "C:\jpgs"
$masters = "C:\masters"
$destination = "C:\new"

# stocker tous les noms de base et les dossiers parent nécessaires à mettre en correspondance dans un tableau
$namesToMatch = @()
gci $jpgs -File -Recurse | select -ExpandProperty FullName -Uniq | % {
    # BaseName et le(s) dossier(s) parent(s) (par exemple "\Armouries\IMG_1286")
    $namesToMatch += (($_ -split "\\jpgs")[-1] -split "\.")[0]
}

# évaluer chaque fichier que nous pourrions avoir besoin de copier
gci $masters -File -Recurse | select -ExpandProperty FullName -Uniq | % {

    # BaseName et le(s) dossier(s) parent(s) (par exemple "\Armouries\IMG_1286")
    $name = (($_ -split "\\masters")[-1] -split "\.")[0]
    # chemin + Fullname, dans la structure de dossier "new" (par exemple "C:\new\Armouries\IMG_1286.jpg")
    $desiredDestination = $_ -replace "masters","new"
    # chemin dans la structure de dossier "new" sans nom de fichier (par exemple "C:\new\Armouries")
    $desiredDestination_noFile = $desiredDestination.Substring(0,$desiredDestination.LastIndexOf("\"))

    # si nous devons copier ce fichier
    if($name -in $namesToMatch) {

        # créer les répertoires parents si nécessaire
        if(!(Test-Path -Path $desiredDestination_noFile)) {
            md -force $desiredDestination_noFile | Out-File null
        }

        # copier le fichier
        cp $_ $desiredDestination

    }
}

2voto

Hamza Azad Points 2327

Cette réponse suppose les mêmes conventions que dans la question, c'est-à-dire que les masters sont dans z:\masters et les JPG sont dans z:\jpgs. Le dossier de destination est supposé être z:\dest.

Réponse courte

dir -File -Recurse z:\masters\ | % { if (dir -Recurse  "z:\jpgs\$($_.BaseName).jpg") { mkdir -ErrorAction SilentlyContinue $($_.Directory -replace "\\masters\\", "\dest\"); cp $_.FullName $($_.FullName -replace "\\masters\\", "\dest\")} }

Explication courte : pour chaque fichier dans z:\masters ou l'un de ses sous-répertoires directs et indirects, il vérifie si l'un des sous-répertoires directs ou indirects de z:\jpgs contient un fichier JPG avec le même nom de base, et si c'est le cas, il copie le fichier principal dans le dossier de destination après avoir créé les répertoires parent si nécessaire.

Vous pouvez tester cette solution en ligne. (Remarque : la version en ligne utilise / comme séparateur de chemin au lieu de \ car elle s'exécute sur Linux, et New-Item -Type Répertoire au lieu de mkdir en raison d'une limitation de l'environnement d'exécution en ligne.)

Avec une indentation correcte et les alias développés

Get-ChildItem -File -Recurse z:\masters\ | ForEach-Object {
    if (Get-ChildItem -Recurse  "z:\jpgs\$($_.BaseName).jpg") {
        mkdir -ErrorAction SilentlyContinue $($_.Directory -replace "\\masters\\", "\dest\")
        Copy-Item $_.FullName $($_.FullName -replace "\\masters\\", "\dest\")
    }
}

Explication détaillée

  • dir -File -Recurse z:\masters\ liste tous les fichiers dans z:\masters et ses sous-répertoires (-Recurse). dir est un alias pour Get-ChildItem
  • % est un alias pour ForEach-Object. Il exécute un script (encadré d'accolades {}) pour chaque objet dans le pipeline.
  • $_ est l'objet actuel dans le pipeline (c'est-à-dire l'un des fichiers principaux).
  • dir -Recurse "z:\jpgs\$($_.BaseName).jpg" renvoie tous les fichiers du répertoire z:\jpgs et de ses sous-répertoires qui ont le même nom de base que le fichier principal actuel ($_.BaseName) et une extension .jpg. Il renvoie $null s'il n'y en a pas, ce qui est ensuite converti en $false lorsqu'il est évalué comme condition de l'instruction if.
  • $_.FullName -replace "\\masters\\", "\dest\" est le chemin complet du fichier de destination : c'est le chemin complet du fichier principal ($_.FullName) où \masters\ est remplacé par \dest\ en utilisant l' opérateur -replace. Cela est utilisé pour avoir la même structure de répertoire dans \dest que dans \masters.
  • mkdir -ErrorAction SilentlyContinue $($_.Directory -replace "\\masters\\", "\dest\") crée les dossiers parent du fichier de destination. Cette étape est nécessaire car Copy-Item ne permet pas actuellement (au moment de PowerShell 6.1) de créer des répertoires parents si nécessaire et échoue lorsqu'ils sont manquants. Le paramètre -ErrorAction SilentlyContinue empêche la commande mkdir d'échouer si les répertoires parent existent déjà.
  • Copy-Item $_.FullName $($_.FullName -replace "\\masters\\", "\dest\") copie le fichier principal dans le dossier de destination.

Remarques

Dans l'expression $_.FullName -replace "\\masters\\", "\dest\", les barres obliques inverses (\) sont doublées dans le premier paramètre de -replace mais pas dans le second. Cela est dû au fait que le premier paramètre de l' opérateur -replace est une expression régulière dans laquelle une barre oblique inverse est un caractère spécial qui doit être échappé, tandis que la barre oblique inverse n'est pas un caractère spécial dans la chaîne de remplacement (le deuxième paramètre).

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X