Comment renommer plusieurs fichiers séquentiellement à partir de la ligne de commande?

15

Comment renommer un fichier comme ci-dessous

AS1100801000002.RAW7AGS 
AS1100801001008.RAW7AH4
AS1100801002001.RAW7AH9
AS1100801003002.RAW7AHE
AS1100801004009.RAW7AHT
AS1100801005002.RAW7AHY
AS1100801010002.RAW7AJ3

au nouveau nom

AS1.txt
AS2.txt
AS3.txt
AS4.txt
AS5.txt
AS6.txt
AS7.txt
kamaruz85
la source

Réponses:

22

L' renameoutil fourni avec Ubuntu est assez chaud dans ce genre de choses. Vous pouvez incorporer de petites expressions Perl comme ceci:

rename -n 's/.+/our $i; sprintf("AS%d.txt", 1+$i++)/e' *

Cela vous montrera simplement ce que cela ferait. Retirez le -npour en faire un exercice de tir réel.

Cela fonctionne essentiellement en définissant grossièrement une variable et en l'incrémentant chaque fichier que nous frappons. Si vous comptez avoir plus de 10 fichiers, je vous suggère d'utiliser un remplissage nul dans le sprintf. Ce qui suit est bon jusqu'à 999:

rename -n 's/.+/our $i; sprintf("AS%03d.txt", 1+$i++)/e' *

... Mais c'est assez facile à développer.

Oli
la source
4

Je ne connais pas de commande ou d'utilitaire unique qui ferait cela, mais c'est assez facile à faire avec une simple boucle:

N=1
for X in AS*RAW*; do
  mv $X AS$N.txt
  N=$(($N+1))
done
Paul
la source
3

Pour améliorer le @ Oli la réponse , l' renameoutil Version 1,600 par Aristote Pagaltzis a fait un compteur intégré, $N.

Donc, tout ce dont vous avez besoin est,

rename 's/AS.*/AS$N/' *

À installer,

  1. brew install renameou Téléchargez le script
  2. Enregistrez-le dans un répertoire sur votre chemin système (généralement /usr/local/bin/brewou /usr/bin)
Atav32
la source
3
Cela semble être un outil différent portant le même nom. La valeur par défaut d'Ubuntu renameest prename. Cela peut être mieux, mais vous voudrez peut-être ajouter des instructions d'installation pour rendre cette réponse plus précieuse.
Oli
1
@Oli bon appel! mis à jour.
Atav32
2

renamevous permet d'affecter directement à $_, ce qui est idéal pour ce problème.

Bien que les arguments de code que nous transmettons à l' renameutilitaire 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. renamevous 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' -noption. Comme il est écrit, cela produirait les noms de fichiers AS01.txt, AS02.txt..., AS10.txt, AS11.txtet ainsi de suite. Vous pouvez les modifier selon vos besoins, puis les supprimer uniquement -nlorsque vous aimez ce que vous voyez.

Si vous souhaitez ajouter une largeur supérieure à 2, remplacez le 2par un plus grand nombre. Par exemple, si pour une raison quelconque vous vouliez des noms de fichiers comme AS00000000000001.txt, vous les remplaceriez %02dpar %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 %02dpar juste %d.

Comment cela marche-t-il? Votre shell se développe * dans une liste de fichiers avant même d'exécuter la renamecommande. La liste est triée lexicographiquement (c'est-à-dire par ordre alphabétique) en fonction de vos paramètres régionaux actuels. renamereç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 $iet définit également la variable $isur 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 renamefichiers é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 sprintfessentiellement 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 /edans 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' sexpression. 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", ++$iserait utilisé comme nom de fichier et non exécuté comme code. Mais l' /eindicateur à 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/ /ecommandes. 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 sdrapeau, qui va à la fin (avec e). Autrement dit, écrivez /seà la fin au lieu de /e.

Eliah Kagan
la source
0

Supposons que les fichiers que vous souhaitez renommer se trouvent dans ~/Adir, et ce sont les seuls fichiers dans ce dossier, puis:

n=0
for f in $( ls ~/Adir | sort ) ; do
    n=$(( n+1 ))
    mv -n "$f" "AS${n}.txt"
done

Ce script va regarder chaque fichier dans ~/Adiret le renommer AS1.txt, AS2.txt, ...si le fichier n'existe pas (il n'y aura pas d'écrasement). C'est pourquoi vous devez vous assurer que ce sont les seuls fichiers dans ~/Adir. La sortcommande est juste au cas où vous voudriez que les fichiers gardent l'ordre initial.

edwin
la source
0

Bien que l'OP nécessite une option de ligne de commande, il est également disponible en tant qu'option GUI dans Nautilus et est assez facile.

Sélectionnez tous les fichiers requis et appuyez sur F2. Il existe une option appelée Numéros automatiques. Vous pouvez l'ajouter au texte dont vous avez besoin.

Sandeep C
la source