rename
vous permet d'affecter directement à $_
, ce qui est idéal pour ce problème.
Bien que les arguments de code que nous transmettons à l' rename
utilitaire Perl effectuent souvent des correspondances et des substitutions (avec s/
), et qu'il est tout à fait acceptable de résoudre ce problème de cette façon , il n'y a vraiment pas besoin de cela dans des cas comme celui-ci où vous n'examinez pas réellement ou réutiliser le texte des anciens noms de fichiers. rename
vous permet d'écrire à peu près n'importe quel code Perl, et il n'a pas besoin d'être intégré à l'intérieur s/
/e
. Je suggère d'utiliser une commande comme celle-ci:
rename -n 'our $i; $_ = sprintf "AS%02d.txt", ++$i' *
Ou, si vous avez envie de raser quelques personnages:
rename -n '$_ = sprintf "AS%02d.txt", ++our$i' *
(Il pourrait être encore plus court, mais non sans sacrifier la clarté.)
Ces deux commandes font la même chose. Chacun montre quelles opérations de changement de nom seraient entreprises. Une fois que vous en avez essayé un et que vous êtes satisfait des résultats, exécutez-le à nouveau sans l' -n
option. Comme il est écrit, cela produirait les noms de fichiers AS01.txt
, AS02.txt
..., AS10.txt
, AS11.txt
et ainsi de suite. Vous pouvez les modifier selon vos besoins, puis les supprimer uniquement -n
lorsque vous aimez ce que vous voyez.
Si vous souhaitez ajouter une largeur supérieure à 2, remplacez le 2
par un plus grand nombre. Par exemple, si pour une raison quelconque vous vouliez des noms de fichiers comme AS00000000000001.txt
, vous les remplaceriez %02d
par %014d
. Si vous ne voulez pas du tout de remplissage - même si cela ferait apparaître vos fichiers dans un ordre non numérique lorsque vous les listeriez plus tard! - alors vous pouvez remplacer %02d
par juste %d
.
Comment cela marche-t-il? Votre shell se développe *
dans une liste de fichiers avant même d'exécuter la rename
commande. La liste est triée lexicographiquement (c'est-à-dire par ordre alphabétique) en fonction de vos paramètres régionaux actuels. rename
reçoit les noms de fichiers en tant qu'arguments de ligne de commande et les traite dans l'ordre dans lequel ils sont répertoriés. L'expression est ++$i
évaluée à une valeur supérieure à la valeur actuelle de la variable $i
et définit également la variable $i
sur cette nouvelle valeur incrémentée. Cette valeur est passée à sprintf
, qui la formate et la place dans un autre texte. Ce texte est directement affecté à la variable spéciale $_
, qui contient le nom de fichier. Les rename
fichiers étant traités dans l'ordre où ils sont passés en arguments, ils sont numérotés en conséquence.
Vous avez peut-être remarqué la similitude avec la réponse d' Oli !
Les deux déclarent et incrémentent une variable de compteur, et les deux utilisent sprintf
essentiellement de la même manière pour incorporer la valeur de ce compteur, complétée à gauche par des zéros, dans l'autre texte des nouveaux noms de fichiers. (Les informations dans les deux réponses sur la façon de remplir avec des zéros - et de changer la largeur de remplissage - s'appliquent même aux deux.) La raison pour laquelle elles sont si similaires est que la méthode de cette réponse plus ancienne ne fait que cela 1 , mais avec des étapes supplémentaires qui sont utiles pour de nombreux problèmes mais pas réellement nécessaires pour celui-ci.
À titre de comparaison, voici à quoi ressemble la deuxième commande de cette réponse si elle est modifiée pour utiliser le style que j'ai utilisé ici (et pour remplir à une largeur de 2, comme je l'ai fait ici, au lieu de 3):
rename -n 's/.+/our $i; sprintf "AS%02d.txt", ++$i/e' *
La partie entre s/.+/
et /e
dans cette commande est maintenant la même que l'expression à laquelle j'assigne $_
(c'est- à -dire le code sur le côté droit de l' =
opérateur) dans la première commande de cette réponse.
- L'
s/
opérateur tente de faire correspondre le texte (noms de fichiers à partir desquels votre shell s'est développé *
et transmis en tant qu'arguments de ligne de commande lors de son exécution rename
) avec une expression régulière et effectue une substitution. /
est utilisé comme délimiteur pour séparer les différentes parties de l' s
expression. La première partie,, .+
est l'expression régulière; elle correspond à tout 1 caractère ( .
) , et le fait une ou plusieurs fois ( +
) . Étant donné que les noms de fichiers ne sont jamais vides - ils sont toujours au moins un caractère à long - ce qui est une façon de correspondre à tout 1 nom de fichier.
- Ensuite, il produit du texte à partir de chaque correspondance - c'est-à-dire de chaque nom de fichier entier - constitué de
our $i; sprintf "AS%02d.txt", ++$i
. Cela produit le nouveau nom de fichier. En règle générale, on utilise s/
pour produire du texte qui soit (a) remplace le texte qui ne correspond qu'à une partie du nom de fichier, ou (b) basé sur le texte correspondant d'une certaine manière (par exemple, il peut utiliser une variable spéciale comme $&
celle qui se développe pour le match). Dans ce cas, cependant, le texte correspondant n'est pas utilisé du tout.
- Normalement, le texte substitué
our $i; sprintf "AS%02d.txt", ++$i
serait utilisé comme nom de fichier et non exécuté comme code. Mais l' /e
indicateur à la fin fait que ce texte est traité comme du code source Perl et évalué, et utilise la valeur produite en le faisant (dans ce cas, la valeur de retour de la fonction intégrée de Perl sprintf
) comme nouveau nom de fichier.
Bien que je pense que la méthode que j'ai montrée ici est une approche plus claire et plus simple pour ce problème que n'importe quelle méthode qui utilise s/
avec /e
, il est bon d'être au courant de cette technique, car elle est bien adaptée à un certain nombre d'autres problèmes de changement de nom de fichier où tous ou une partie des noms de fichiers originaux est examinée et / ou conservée. Je recommande cet article de blog par Oli (qui a également écrit cette réponse ), qui comprend de tels exemples.
1 Techniquement, il existe une différence dans le comportement des $_ =
commandes et des s/
/e
commandes. Dans l'expression régulière .+
, ce n'est pas strictement vrai qui .
correspond à n'importe quel caractère, car il ne correspond pas à une nouvelle ligne . Vous ne devriez probablement pas utiliser de noms de fichiers contenant des retours à la ligne, mais vous pouvez, et parfois un fichier est nommé ainsi par accident. Si vous en avez envie, contrastez la sortie de rename -n 'our $i; $_ = sprintf "AS%02d.txt", ++$i' $'foo\nbar'
celle de rename -n 's/.+/our $i; sprintf "AS%02d.txt", ++$i/e' $'foo\nbar'
. Pour faire .
correspondre une nouvelle ligne, utilisez le s
drapeau, qui va à la fin (avec e
). Autrement dit, écrivez /se
à la fin au lieu de /e
.
rename
est prename. Cela peut être mieux, mais vous voudrez peut-être ajouter des instructions d'installation pour rendre cette réponse plus précieuse.