0
votes

Comment tronquer récursivement les noms de fichiers dans PowerShell?

J'ai besoin de tronquer les noms de fichiers à 35 caractères (y compris l'extension) alors j'ai exécuté ce script et cela a fonctionné pour le répertoire lui-même (PowerShell, Windows 10).

Rename-Item : Error in input to script block for parameter 'NewName'. Exception when calling "Substring" with the arguments "2": "The index and length must reference a location in the string. Parameter name: length"
On line: 1 Character: 62
+ ... *.pdf | Rename-Item -NewName {$_.Name.substring(0,31) + $_.Extension}
+                                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (C:\User\prsn..._file_name_long.pdf:PSObject) [Rename-Item], ParameterBindingException
    + FullyQualifiedErrorId : ScriptBlockArgumentInvocationFailed,Microsoft.PowerShell.Commands.RenameItemCommand

Ensuite, j'ai voulu appliquer le même script, y compris les sous-répertoires:

Get-ChildItem -Recurse -Include *.pdf | Rename-Item -NewName {$_.Name.substring(0,31) + $_.Extension}

Ce script m'a donné une erreur comme celle-ci pour chaque fichier:

Get-ChildItem *.pdf | rename-item -NewName {$_.name.substring(0,31) + $_.Extension} 

I essayé celui-ci mais il ne va pas dans les sous-répertoires: Commande pour tronquer tous les noms de fichiers à 255 caractères

J'ai trouvé celui-ci mais il n'a pas de réponse: https://superuser.com/questions/1188711/ comment-tronquer-récursivement les noms de fichiers et les noms de répertoires dans PowerShell


0 commentaires

3 Réponses :


1
votes

Utilisez l'opérateur regex -replace pour supprimer tout ce qui se trouve après les 35 premiers caractères - il ignorera simplement toute chaîne qui n'a pas au moins 35 caractères et la renverra telle quelle:

$_.Name -replace '(?<=^.{35}).*$'


0 commentaires

1
votes

Je ne pense pas que vous puissiez utiliser $ _ de cette façon. Je pense que vous devez l'envelopper dans une boucle ForEach pour que les références fonctionnent de cette façon. Une fois que cela est fait, vous devrez également spécifier le chemin du fichier que vous souhaitez renommer:

Quelque chose comme:

Get-ChildItem -Recurse -Include *.pdf -File | 
    ForEach-Object{        
        Rename-Item -Path $_.FullName -NewName ( ($_.Name -replace '(?<=^.{35}).*$') + $_.Extension )
        }

Remarquez que j'ai utilisé des parenthèses au lieu de curly croisillons. Si vous utilisez un bloc de script, il peut ne pas être évalué. Il y a d'autres façons d'y arriver, mais je pense que l'utilisation de parenthèses est la plus évidente.

Remarquez que j'ai utilisé $ _. BaseName au lieu de name. Le nom de base n'inclut pas l'extension. même si je ne sais pas comment fonctionne votre sous-chaîne, je l'ai laissé à vous de décider.

Vous pouvez combiner cela avec Réponse de @ Mathias ou une modification de celle-ci. Cela pourrait vous donner un moyen meilleur ou plus fiable de dériver le nouveau nom de fichier. Je ne l'ai pas testé, mais il pourrait ressembler à quelque chose comme:

Get-ChildItem -Recurse -Include *.pdf -File | 
ForEach-Object{
    Rename-Item -Path $_.FullName -NewName ( $_.BaseName.SubString(0, 31) + $_.Extension )
    }


2 commentaires

La première réponse génère une erreur lorsqu'un nom de fichier est inférieur à 35 (fonctionne toujours très bien). La deuxième réponse supprime l'extension de fichier.


@ 7cc, Oui, j'ai eu le même problème, et je m'y attendais franchement avec l'indexation SubString. Malheureusement, il nous reste parfois à supposer, dans ce cas, qu'il existe une attente fiable de la longueur du nom de fichier. S'il nous restait à écrire pour chaque problème possible avec une approche donnée, nous n'irions pas très loin. Si cela ne vous dérange pas, je vais incorporer dans les exemples ci-dessus.



1
votes

Le message d'erreur correct est
Exception appelant "Substring" avec "2" argument (s): "L'index et la longueur doivent faire référence à un emplacement dans la chaîne.

La raison en est que le deuxième argument est supérieur à la longueur de le nom du fichier, par exemple "abc" .Substring (0,4) jette.

Réponse

dir *.pdf -File -Recurse | Rename-Item -NewName {
  $_.name.substring(0, [Math]::Min($_.BaseName.length, 31)) + ".pdf"
}

ou p>

$renameTarget = dir -File -Recurse *.pdf | ? { $_.Name.Length -gt 35 }
$renameTarget | Rename-Item -NewName {
  $_.name.substring(0, 31) + ".pdf"
}


0 commentaires