J'écris un script simple pour supprimer les dossiers de migration USMT après un certain nombre de jours:
## Server List ##
$servers = "Delorean","Adelaide","Brisbane","Melbourne","Newcastle","Perth"
## Number of days (-3 is over three days ago) ##
$days = -3
$timelimit = (Get-Date).AddDays($days)
foreach ($server in $servers)
{
$deletedusers = @()
$folders = Get-ChildItem \\$server\USMT$ | where {$_.psiscontainer}
write-Host "Checking server : " $server
foreach ($folder in $folders)
{
If ($folder.LastWriteTime -lt $timelimit -And $folder -ne $null)
{
$deletedusers += $folder
Remove-Item -recurse -force $folder.fullname
}
}
write-Host "Users deleted : " $deletedusers
write-Host
}
Cependant, je continue de frapper le redouté Remove-Item : The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters.
J'ai étudié des solutions de contournement et des alternatives, mais elles tournent toutes autour de moi en se souciant de ce qui se trouve dans le dossier.
J'espérais une solution plus simple car je ne me soucie pas vraiment du contenu du dossier s'il est marqué pour suppression.
Existe-t-il une applet de commande Powershell native autre que Remove-Item -recurse qui peut accomplir ce que je recherche?
Il s'agit d'une limitation connue de PowerShell
. La solution consiste à utiliser dir
cmd (désolé, mais c'est vrai).
http://asysadmin.tumblr.com/post/17654309496/powershell-path-length-limitation
ou comme mentionné par la réponse AaronH, utilisez la syntaxe \?\dans cet exemple pour supprimer la construction
dir -Include build -Depth 1 | Remove-Item -Recurse -Path "\\?\$($_.FullName)"
J'ai souvent ce problème avec les projets de nœuds. Ils imbriquent leurs dépendances et une fois git cloné, il est difficile de les supprimer. Un utilitaire de nœud agréable que j'ai rencontré est rimraf .
npm install rimraf -g
rimraf <dir>
Tout comme CADII l'a dit dans une autre réponse: Robocopy est capable de créer des chemins plus longs que la limite de 260 caractères. Robocopy est également capable de supprimer ces chemins. Vous pouvez simplement mettre en miroir un dossier vide sur votre chemin contenant des noms trop longs au cas où vous voudriez le supprimer.
Par exemple:
robocopy C:\temp\some_empty_dir E:\temp\dir_containing_very_deep_structures /MIR
Voici le référence Robocopy pour connaître les paramètres et les différentes options.
Cette réponse sur SuperUser l'a résolu pour moi: https://superuser.com/a/274224/85532
Cmd /C "rmdir /S /Q $myDir"
J'ai créé une fonction PowerShell qui est capable de supprimer un long chemin (> 260) en utilisant la technique de robocopy mentionnée :
function Remove-PathToLongDirectory
{
Param(
[string]$directory
)
# create a temporary (empty) directory
$parent = [System.IO.Path]::GetTempPath()
[string] $name = [System.Guid]::NewGuid()
$tempDirectory = New-Item -ItemType Directory -Path (Join-Path $parent $name)
robocopy /MIR $tempDirectory.FullName $directory | out-null
Remove-Item $directory -Force | out-null
Remove-Item $tempDirectory -Force | out-null
}
Exemple d'utilisation:
Remove-PathToLongDirectory c:\yourlongPath
Il y a quelque temps, j'ai appris une astuce qui fonctionne souvent pour contourner les problèmes de chemin d'accès aux fichiers longs. Apparemment, lors de l'utilisation de certaines API Windows, certaines fonctions transitent par du code hérité qui ne peut pas gérer les noms de fichiers longs. Cependant, si vous formatez vos chemins d'une manière particulière, le code hérité est évité. L'astuce qui résout ce problème consiste à référencer les chemins à l'aide du préfixe "\\? \". Il convient de noter que toutes les API ne prennent pas en charge cela, mais dans ce cas particulier, cela a fonctionné pour moi, voir mon exemple ci-dessous:
L'exemple suivant échoue:
PS D:\> get-childitem -path "D:\System Volume Information\dfsr" -hidden
Directory: D:\System Volume Information\dfsr
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a-hs 10/09/2014 11:10 PM 834424 FileIDTable_2
-a-hs 10/09/2014 8:43 PM 3211264 SimilarityTable_2
PS D:\> Remove-Item -Path "D:\System Volume Information\dfsr" -recurse -force
Remove-Item : The specified path, file name, or both are too long. The fully qualified file name must be less than 260
characters, and the directory name must be less than 248 characters.
At line:1 char:1
+ Remove-Item -Path "D:\System Volume Information\dfsr" -recurse -force
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : WriteError: (D:\System Volume Information\dfsr:String) [Remove-Item], PathTooLongExcepti
on
+ FullyQualifiedErrorId : RemoveItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand
PS D:\>
Cependant, le préfixe du chemin avec "\\? \" Permet à la commande de fonctionner correctement:
PS D:\> Remove-Item -Path "\\?\D:\System Volume Information\dfsr" -recurse -force
PS D:\> get-childitem -path "D:\System Volume Information\dfsr" -hidden
PS D:\>
Si vous avez Ruby installé, vous pouvez utiliser Fileman:
gem install fileman
Une fois installé, vous pouvez simplement exécuter ce qui suit dans votre invite de commande:
fm rm your_folder_path
Ce problème est une vraie douleur dans le cou lorsque vous développez dans node.js sur Windows, donc fileman devient vraiment pratique pour supprimer toutes les ordures de temps en temps
Si tout ce que vous faites est de supprimer les fichiers, j'utilise une fonction pour raccourcir les noms, puis je supprime.
function ConvertTo-ShortNames{
param ([string]$folder)
$name = 1
$items = Get-ChildItem -path $folder
foreach ($item in $items){
Rename-Item -Path $item.FullName -NewName "$name"
if ($item.PSIsContainer){
$parts = $item.FullName.Split("\")
$folderPath = $parts[0]
for ($i = 1; $i -lt $parts.Count - 1; $i++){
$folderPath = $folderPath + "\" + $parts[$i]
}
$folderPath = $folderPath + "\$name"
ConvertTo-ShortNames $folderPath
}
$name++
}
}
Je sais que c'est une vieille question, mais j'ai pensé que je mettrais cela ici au cas où quelqu'un en aurait besoin.
Il existe une solution de contournement qui utilise Experimental.IO à partir du projet Base Class Libraries . Vous pouvez le trouver sur poshcode , ou le télécharger sur blog de l'auteur . La limitation 260 est dérivée de . NET , c'est donc ça, ou utiliser des outils qui ne dépendent pas de .NET (comme cmd /c dir
, comme @Bill l'a suggéré).
Cela vieillit mais j'ai récemment dû le contourner. J'ai fini par utiliser "subst" car il ne nécessitait aucun autre module ou fonction sur le PC sur lequel il fonctionnait. Un peu plus portable.
Fondamentalement, trouvez une lettre de lecteur de rechange, "subst" le long chemin vers cette lettre, puis utilisez-la comme base pour GCI.
La seule limitation réside dans le fait que $ _. Fullname et les autres propriétés signalent la lettre de lecteur comme chemin racine.
Semble fonctionner correctement:
$location = \\path\to\long\
$driveLetter = ls function:[d-z]: -n | ?{ !(test-path $_) } | random
subst $driveLetter $location
sleep 1
Push-Location $driveLetter -ErrorAction SilentlyContinue
Get-ChildItem -Recurse
subst $driveLetter /D
Cette commande n'est évidemment pas de supprimer des fichiers mais peut être substituée.
PowerShell peut facilement être utilisé avec AlphaFS.dll pour effectuer des tâches d'E/S de fichier réelles sans les tracas PATH TOO LONG.
Par exemple:
Import-Module <path-to-AlphaFS.dll>
[Alphaleonis.Win32.Filesystem.Directory]::Delete($path, $True)
Veuillez consulter Codeplex: https://alphafs.codeplex.com/ pour ce projet .NET.
La combinaison d'outils peut mieux fonctionner, essayez de faire un dir/x pour obtenir le nom de fichier 8.3 à la place. Vous pouvez ensuite analyser cette sortie dans un fichier texte, puis créer un script PowerShell pour supprimer les chemins que vous avez sortis. Prenez-vous tous une minute. Alternativement, vous pouvez simplement renommer le nom de fichier 8.3 en quelque chose de plus court, puis le supprimer.
Pour ma Robocopy travaillé en 1, 2 et 3
Juste pour être complet, je l'ai rencontré quelques fois de plus et j'ai utilisé une combinaison de "subst" et de "New-PSDrive" pour contourner ce problème dans diverses situations.
Pas exactement une solution, mais si quelqu'un cherche des alternatives, cela pourrait aider.
Subst semble très sensible au type de programme que vous utilisez pour accéder aux fichiers, parfois cela fonctionne et parfois non, semble être le même avec New-PSDrive.
J'ai eu le même problème en essayant de supprimer des dossiers sur une machine distante.
Rien n'a aidé mais ... j'ai trouvé une astuce:
# 1:let's create an empty folder
md ".\Empty" -erroraction silentlycontinue
# 2: let's MIR to the folder to delete : this will empty the folder completely.
robocopy ".\Empty" $foldertodelete /MIR /LOG+:$logname
# 3: let's delete the empty folder now:
remove-item $foldertodelete -force
# 4: we can delete now the empty folder
remove-item ".\Empty" -force
Fonctionne comme un charme sur les dossiers locaux ou distants (en utilisant le chemin UNC)
Toute chose développée à l'aide de .NET prête à l'emploi échouera avec des chemins trop longs. Vous devrez les déplacer vers 8.3 noms , appels PInVoke (Win32) , ou utiliser robocopy
Ajout à la solution de Daniel Lee, lorsque $ myDir a des espaces au milieu, il donne des erreurs FILE NOT FOUND en considérant un ensemble de fichiers séparés de l'espace. Pour surmonter cela, utilisez des citations autour de la variable et mettez le caractère d'échappement PowerShell pour ignorer les quatations.PS>cmd.exe /C "rmdir /s /q <Grave-accent>"$myDir<Grave-accent>""
Veuillez remplacer le caractère d'accent grave approprié au lieu de <Grave-accent>
SO joue avec moi et je ne peux pas l'ajouter :). J'espère que quelqu'un le mettra à jour pour que d'autres le comprennent facilement