Comment supprimer les caractères de fin dans les noms de fichiers dans Bash?

13

J'ai un tas de fichiers multimédias comme ceux ci-dessous:

tvshow.s01e11]Bloodlines.avi
tvshow.s01e12]suffer.avi
tvshow.s01e13]NotMe.avi

Je voudrais les renommer

tvshow.s01e11.avi
tvshow.s01e12.avi
tvshow.s01e13.avi

J'ai essayé d'utiliser le changement de nom, mais il est évident que je n'obtiens pas la bonne syntaxe car elle échoue.

Widgeteye
la source
Si jamais vous voulez faire ça dans un gui, krenamec'est adorable. Il a toutes sortes d'options puissantes et vous montre ce qu'il va faire avant qu'il ne le fasse réellement. Vous pouvez même l'utiliser pour tester des modèles que vous pourrez utiliser plus tard dans bash.
Joe

Réponses:

14

En shell, on pourrait faire simplement:

for x in *]*.avi ; do 
    mv -i "$x" "${x%]*.avi}.avi"
done

Le shell peut produire une liste des noms de fichiers avec juste un glob régulier, et ${var%pattern}supprime le motif de correspondance (le plus court) de la fin de la chaîne en variable var. Étant donné que l'extension finale est toujours .avi, je viens de la supprimer avec le motif et de la rajouter. Avec les guillemets, cela devrait aussi fonctionner avec les noms de fichiers contenant des espaces, commeFancy Name for a Show.s01e01]Asdf.avi

ilkkachu
la source
@NoviceC le modèle extglob n'était pas une mauvaise idée. En fait, quelque chose comme ${x/]*([^.])}devrait faire, il supprime un crochet et un nombre quelconque de non-points. (mais échoue s'il y a d'autres crochets ou points, car il n'est pas verrouillé à la fin de la chaîne)
ilkkachu
C'est un bon point. Mais j'ai vraiment trop compliqué le problème alors que j'aurais dû y aller ${x/]*.avi}et en ajouter un .avicomme vous. Mais je n'étais pas non plus satisfait de la façon dont les espaces du nom se briseraient (`find . -name '*]*.avi'`). J'étais heureux de fournir une méthode de commande standard unix limitée, car le changement de nom ne l'est pas, mais cela souffle le mien hors de l'eau.
Novice C
2

C'est toutes sortes d'impraticables - les autres réponses sont beaucoup plus rapides et plus courtes - mais ...

Vous pouvez utiliser PowerShell! Microsoft l' open source récemment et l'a fait multiplateforme. Pour les téléchargements et les instructions d'installation de votre système d'exploitation, consultez la section «Get PowerShell» .

Une fois installé, vous pouvez utiliser ce bref script:

Get-ChildItem -File '*]*.avi' | ForEach-Object {
    Rename-Item $_ -NewName (($_.Name -Split ']')[0] + '.avi')
}

Fondamentalement, il parcourt chaque objet du répertoire actuel qui correspond à un fichier *]*.avi, obtient la partie avant le support, y .avirevient et l'attribue comme nouveau nom.

Pour l'exécuter directement à partir de Bash, utilisez ce monoplace semi-golfée:

powershell -command $'gci -File \'*]*.avi\'|%{rename-item $_ -NewName (($_.Name -Split \']\')[0]+\'.avi\')}'

Citation échappant à la courtoisie de cette réponse Stack Overflow .

(Testé dans Bash sur Ubuntu sur Windows. Il y a probablement une manière beaucoup plus courte de le faire avec PowerShell, mais je voulais montrer quelque chose qui est compréhensible pour les gens qui ne connaissent pas les expressions régulières.)

Ben N
la source
Rube Goldberg serait fier! Les regex sont un véritable PITA à apprendre, mais elles en valent la peine plusieurs fois - même au niveau rudimentaire, je peux les utiliser.
Joe
1

Debian a un paquet appelé mmv qui pourrait également être disponible dans d'autres distributions, et devrait être assez facile à compiler à partir des sources sinon. Il vous permet d'écrire ceci:

mmv '*]*.avi' '#1.avi'

Vous pouvez lire la page de manuel Ubuntu pour cette commande pour plus de détails.

MvG
la source
0

Cela recherchera le motif et remplacera le texte à l'aide de sed.

 $sed 's/\(.*]\)[a-zA-z0-9].*\(.avi\)/\1\2/' filename
Tejender Mohan
la source