Remplacer tous les deux-points des noms de fichiers par le terminal

12

J'ai un Go de musique sur mon disque dur formaté avec EXT4. Je souhaite déplacer ces fichiers vers une partition HDD au format FAT. Cependant, je ne peux pas déplacer la plupart de mes fichiers car ils contiennent ":" dans les noms (par exemple, "Acte 2: ....." pour les opéras). Existe-t-il un moyen avec la ligne de commande pour renommer tous mes fichiers de "XXXX: XXXX" à "XXXX-XXXX"?

Ryan McClure
la source

Réponses:

25

Si tous vos fichiers se trouvent dans un seul répertoire, essayez:

rename 's|:|-|g' *

(où * peut être changé en quelque chose de plus restrictif si vous le souhaitez)

Si vous avez plusieurs fichiers dans une arborescence de répertoires, essayez ceci à partir de la base de l'arborescence:

find . -name "*:*" -exec rename 's|:|-|g' {} \;

Vous pouvez ajouter l'option -njuste après renamepour qu'elle vous dise ce qu'elle ferait sans le faire réellement. Cela pourrait vous aider à éviter de marcher accidentellement sur d'autres fichiers ou autre chose de mal ...

AeroGT80
la source
1
La solution de répertoire unique fonctionnera mais la solution imbriquée ne fonctionnera pas si les répertoires eux-mêmes ont: s dans leurs noms. En effet, dans la sortie du find .nom d'un sous-répertoire précède son contenu. Donc, si vous avez un fichier en /1:/2:premier /1:/sera renommé /1-/. Maintenant , vous ne pouvez pas renommer /1:/2:à /1-/2-cause /1:/2:n'existe pas.
S Prasanth
1
Pour les répertoires: find . -type d -readable -writable -exec rename 's|:|-|g' {} \;Et puis les fichiers:find . -type f -readable -writable -exec rename 's|:|-|g' {} \;
@Christopher La commande des répertoires échouera s'il existe deux niveaux de répertoires avec: dans leurs noms. Par exemple: / 1: / 2: / où 2: est également un répertoire. Bien sûr, si ce n'est pas le cas dans la situation de Ryan, cela fonctionnera.
S Prasanth
Pour plusieurs niveaux de sous-dirs utiliser: for i in {1..20}; do find . -maxdepth $i -mindepth $i -name "*:*" -exec rename 's|:|-|g' {} \;; done. Modifiez 20 à la profondeur maximale du dir. structure. Ne doit pas être exact - peut être plus grand. Cela prendra du temps s'il est réglé sur un très grand nombre.
S Prasanth
0

Je ne suis pas sur ma machine Linux pour le moment, je ne peux donc donner que des informations approximatives.

Linux a un utilitaire de ligne de commande appelé renamequi fonctionne avec, entre autres, des expressions régulières ou des expressions régulières. Vous devriez pouvoir l'utiliser avec une expression régulière comme "s /: / - /" sur vos fichiers pour obtenir le renommage que vous souhaitez.

Juste pour être sûr, faites-le en petits lots et / ou premier test avec la simulation (renommer a un drapeau qui vous donne juste l'ancien nom et le nouveau nom du fichier sans réellement renommer - utilisez-le pour vérifier d'abord)

Karthik T
la source
0

Il s'agit d'une solution en python qui gère le cas où les fichiers ne sont pas nécessairement dans le même répertoire.

import os
torename = []
rootdir = "The main directory"
logfile = "Path to log file" #Eg: logfile = "/home/prasanth/renamelog"
for (path, dirs, files) in os.walk(rootdir):
    for dirname in dirs:
        if ':' in dirname:
            torename.append(os.path.join(path, dirname))
    for filename in files:
        if ':' in filename:
            torename.append(os.path.join(path, filename))

print "No of files/dirs to rename =", len(torename)
a = raw_input("Continue? (y/n) ")
if a == 'y':
    torename.reverse()
    for oldname in torename:
        directory, filename = os.path.split(oldname)
        newname = os.path.join(directory, filename.replace(':', '-'))
        command = 'mv %s %s > /dev/null' % (repr(oldname), repr(newname))
        os.system(command)
        f = open(logfile, 'a')
        f.write(oldname + '\n')
        f.close()
else:
    print "Aborted."
  1. Enregistrez-le dans un fichier (par exemple) rename.py.
  2. Passez rootdirau répertoire le plus à l'extérieur considéré (utilisez le nom de chemin complet commençant par /. Pas de raccourcis ou de variables env comme ~ autorisé). Pas besoin de mettre \ avant les caractères spéciaux - par exemple, si le répertoire le plus à l'extérieur est /.../Mon disque dur, mettez rootdir = "/.../My HDD"NOT rootdir = "/.../My\ HDD"(notez le "s) [Je ne suis explicite que parce que vous ne connaissez peut-être pas python. prévu.]
  3. Passez logfileà l'emplacement souhaité du fichier journal. À la fin, ce fichier contiendra la liste des fichiers renommés - pour référence future.
  4. Appelle python rename.py.

Avertissement: effectuez un test sur un petit échantillon avant de risquer un Go entier de musique.

Détails: le changement de nom s'effectue à partir des fichiers les plus internes vers l'extérieur.

S Prasanth
la source
0

Je me rends compte que c'est un très vieux poste. La solution récursive d'AeroGT80 est très complète, mais elle est assez lente. Je l'ai fait fonctionner pendant environ une demi-heure sur un serveur plus lent et cela n'a été fait qu'à moitié - je pense qu'il s'agissait d'environ 73 000 fichiers dans environ 300 sous-répertoires.

La solution ci-dessous fonctionnera beaucoup plus rapidement (elle fonctionne sur tous les fichiers d'un répertoire, au lieu de chaque fichier un par un - en utilisant la solution non récursive d'AeroGT80). Le seul problème est qu'il ne descend que dans un répertoire en profondeur (il n'est donc pas entièrement récursif comme sa solution), mais je suis sûr qu'il pourrait être modifié assez facilement.

#!/bin/bash
for D in *; do
        if [ -d "${D}" ]; then
                #echo "${D}"
                pushd "${D}" > /dev/null
                rename 's|:|-|g' *
                popd > /dev/null
        fi
done
Adam Plocher
la source