Créer un répertoire s'il n'existe pas

342

J'écris un script PowerShell pour créer plusieurs répertoires s'ils n'existent pas.

Le système de fichiers ressemble à ceci

D:\
D:\TopDirec\SubDirec\Project1\Revision1\Reports\
D:\TopDirec\SubDirec\Project2\Revision1\
D:\TopDirec\SubDirec\Project3\Revision1\
  • Chaque dossier de projet a plusieurs révisions.
  • Chaque dossier de révision a besoin d'un dossier Rapports.
  • Certains des dossiers «révisions» contiennent déjà un dossier Rapports; cependant, la plupart n'en ont pas.

J'ai besoin d'écrire un script qui s'exécute quotidiennement pour créer ces dossiers pour chaque répertoire.

Je peux écrire le script pour créer un dossier, mais la création de plusieurs dossiers est problématique.

ecollis6
la source
3
"créer plusieurs dossiers est problématique" - quel genre de problème rencontrez-vous? Vous ne savez pas comment écrire la morue? Recevez-vous un message d'erreur? Les dossiers n'apparaissent-ils tout simplement pas après l'exécution du script? Différents problèmes nécessitent des solutions différentes.
LarsH

Réponses:

537

Essayez le -Forceparamètre:

New-Item -ItemType Directory -Force -Path C:\Path\That\May\Or\May\Not\Exist

Vous pouvez utiliser Test-Path -PathType Containerpour vérifier d'abord.

Consultez l' article d' aide MSDN sur les nouveaux éléments pour plus de détails.

Andy Arismendi
la source
101
Pour les paresseux, il y a un raccourci: md -Force c: \ foo \ bar \ baz
Matthew Fellows
74
Pour ceux qui ne veulent pas de sortie lorsque le dossier est créé, ajoutez "| Out-Null" à la fin
armannvg
20
Que fera -Force réellement? La documentation indique "Force cette applet de commande à créer un élément qui écrase un élément en lecture seule existant" . Va-t-il supprimer un dossier existant? Cela devrait être clair dans cette réponse.
Peter Mortensen
25
@PeterMortensen Dans le cas des répertoires, leur forçage n'efface pas le contenu existant, il supprime uniquement le message d'erreur indiquant qu'il est déjà créé. Cette commande créera également tous les dossiers intermédiaires nécessaires, et le contenu de ces dossiers est également sûr s'il existe déjà.
John Neuhaus
162
$path = "C:\temp\NewFolder"
If(!(test-path $path))
{
      New-Item -ItemType Directory -Force -Path $path
}

Test-Pathvérifie si le chemin existe. Sinon, il créera un nouveau répertoire.

Client
la source
Agréable! Cela rend la sortie silencieuse si le répertoire existe déjà (car il utilise test-path).
Warlike Chimpanzee
17

L'extrait de code suivant vous aide à créer un chemin d'accès complet.

Function GenerateFolder($path) {
    $global:foldPath = $null
    foreach($foldername in $path.split("\")) {
        $global:foldPath += ($foldername+"\")
        if (!(Test-Path $global:foldPath)){
            New-Item -ItemType Directory -Path $global:foldPath
            # Write-Host "$global:foldPath Folder Created Successfully"
        }
    }
}

La fonction ci-dessus divise le chemin d'accès que vous avez transmis à la fonction et vérifie si chaque dossier existe ou non. S'il n'existe pas, il créera le dossier respectif jusqu'à la création du dossier cible / final.

Pour appeler la fonction, utilisez l'instruction ci-dessous:

GenerateFolder "H:\Desktop\Nithesh\SrcFolder"
Naredla Nithesh Reddy
la source
1
Celui-ci n'est pas le plus facile, mais il est facile à comprendre.
Wang Jijun
13

J'ai eu exactement le même problème. Vous pouvez utiliser quelque chose comme ceci:

$local = Get-Location;
$final_local = "C:\Processing";

if(!$local.Equals("C:\"))
{
    cd "C:\";
    if((Test-Path $final_local) -eq 0)
    {
        mkdir $final_local;
        cd $final_local;
        liga;
    }

    ## If path already exists
    ## DB Connect
    elseif ((Test-Path $final_local) -eq 1)
    {
        cd $final_local;
        echo $final_local;
        liga;  (function created by you TODO something)
    }
}
pykimera
la source
11

Lorsque vous spécifiez l' -Forceindicateur, PowerShell ne se plaindra pas si le dossier existe déjà.

Bon mot:

Get-ChildItem D:\TopDirec\SubDirec\Project* | `
  %{ Get-ChildItem $_.FullName -Filter Revision* } | `
  %{ New-Item -ItemType Directory -Force -Path (Join-Path $_.FullName "Reports") }

BTW, pour planifier la tâche, veuillez consulter ce lien: Planification des travaux en arrière-plan .

Klark
la source
10

Utilisation:

$path = "C:\temp\"

If (!(test-path $path))
{
    md C:\Temp\
}
  • La première ligne crée une variable nommée $pathet lui affecte la valeur de chaîne "C: \ temp \"

  • La deuxième ligne est une Ifinstruction qui s'appuie sur l' applet de commande Test-Path pour vérifier si la variable $pathn'existe pas . Le non existe est qualifié à l'aide du !symbole.

  • Troisième ligne: Si le chemin stocké dans la chaîne ci-dessus n'est pas trouvé, le code entre les accolades sera exécuté.

md est la version courte de la saisie: New-Item -ItemType Directory -Path $path

Remarque: je n'ai pas testé en utilisant le -Forceparamètre ci-dessous pour voir s'il y a un comportement indésirable si le chemin existe déjà.

New-Item -ItemType Directory -Path $path
Kyle
la source
1
cela fonctionne également pour une hiérarchie de répertoires, md "C:\first\second\thirdcréez-les tous.
MortenB
9

Il existe trois méthodes que je connais pour créer un répertoire à l'aide de PowerShell:

Method 1: PS C:\> New-Item -ItemType Directory -path "C:\livingston"

Entrez la description de l'image ici

Method 2: PS C:\> [system.io.directory]::CreateDirectory("C:\livingston")

Entrez la description de l'image ici

Method 3: PS C:\> md "C:\livingston"

Entrez la description de l'image ici

George Livingston
la source
Notez que `md` est simplement un alias Powershell par défaut pour `mkdir` (make directory), une commande windows similaire à Linux / Unix mkdir. ref: `Get-Alias
md`
4

D'après votre situation, il semble que vous deviez créer un dossier "Révision #" une fois par jour avec un dossier "Rapports". Si tel est le cas, il vous suffit de connaître le numéro de révision suivant. Écrivez une fonction qui obtient le numéro de révision suivant, Get-NextRevisionNumber. Ou vous pouvez faire quelque chose comme ça:

foreach($Project in (Get-ChildItem "D:\TopDirec" -Directory)){
    # Select all the Revision folders from the project folder.
    $Revisions = Get-ChildItem "$($Project.Fullname)\Revision*" -Directory

    # The next revision number is just going to be one more than the highest number.
    # You need to cast the string in the first pipeline to an int so Sort-Object works.
    # If you sort it descending the first number will be the biggest so you select that one.
    # Once you have the highest revision number you just add one to it.
    $NextRevision = ($Revisions.Name | Foreach-Object {[int]$_.Replace('Revision','')} | Sort-Object -Descending | Select-Object -First 1)+1

    # Now in this we kill two birds with one stone.
    # It will create the "Reports" folder but it also creates "Revision#" folder too.
    New-Item -Path "$($Project.Fullname)\Revision$NextRevision\Reports" -Type Directory

    # Move on to the next project folder.
    # This untested example loop requires PowerShell version 3.0.
}

Installation de PowerShell 3.0 .

MAL
la source
2

Je voulais pouvoir laisser facilement les utilisateurs créer un profil par défaut pour PowerShell pour remplacer certains paramètres, et je me suis retrouvé avec la ligne unique suivante (plusieurs déclarations oui, mais peut être collée dans PowerShell et exécutée à la fois, ce qui était l'objectif principal ):

cls; [string]$filePath = $profile; [string]$fileContents = '<our standard settings>'; if(!(Test-Path $filePath)){md -Force ([System.IO.Path]::GetDirectoryName($filePath)) | Out-Null; $fileContents | sc $filePath; Write-Host 'File created!'; } else { Write-Warning 'File already exists!' };

Pour plus de lisibilité, voici comment je le ferais dans un fichier .ps1 à la place:

cls; # Clear console to better notice the results
[string]$filePath = $profile; # Declared as string, to allow the use of texts without plings and still not fail.
[string]$fileContents = '<our standard settings>'; # Statements can now be written on individual lines, instead of semicolon separated.
if(!(Test-Path $filePath)) {
  New-Item -Force ([System.IO.Path]::GetDirectoryName($filePath)) | Out-Null; # Ignore output of creating directory
  $fileContents | Set-Content $filePath; # Creates a new file with the input
  Write-Host 'File created!';
}
else {
  Write-Warning "File already exists! To remove the file, run the command: Remove-Item $filePath";
};
Johny Skovdal
la source
1

En voici une simple qui a fonctionné pour moi. Il vérifie si le chemin existe, et si ce n'est pas le cas, il créera non seulement le chemin racine, mais aussi tous les sous-répertoires:

$rptpath = "C:\temp\reports\exchange"

if (!(test-path -path $rptpath)) {new-item -path $rptpath -itemtype directory}
tklone
la source