Comment renommer des fichiers et remplacer des caractères?


11

J'ai un groupe de fichiers qui ont :(deux points) dans le nom. Je dois remplacer le :par -(tiret).

Existe-t-il un moyen simple de le faire dans un script?

Exemple de nom de fichier: 2013-10-11:11:52:08_055456663_045585_.txt

Réponses:


17

Une simple doublure devrait faire (en supposant une shcoque compatible Posix ):

for f in *:*; do mv -v "$f" $(echo "$f" | tr ':' '-'); done

Explication:

  • for ... in ...; do ...; doneest une boucle

  • *:* correspond à tous les fichiers et répertoires du répertoire courant qui ont :leur nom

  • f est affecté à son tour à chacun de ces noms de fichiers dans la boucle

  • mvrenomme son premier argument en second; -v(verbeux) lui demande d'imprimer ce qu'il fait; cette option est spécifique à GNU-utils , elle est donc disponible sur Linux mais pas Solaris

  • $(...) exécute le code dans un sous-shell et remplace la sortie

  • echo imprime son argument sur la sortie standard

  • tr lit la sortie standard et traduit les caractères selon la carte fournie

Si vous utilisez bash , vous pouvez éviter de générer un shell supplémentaire ( $()) avec des sous-processus ( tr) en le remplaçant $(...)par ${f//:/-}.


+1 pour une réponse de travail simple, mais cela pourrait faire avec un peu plus d'explications. Par exemple, la for f inboucle ... est une boucle qui itère sur tous les fichiers du répertoire courant où les fichiers doivent correspondre *:*. (Que se passe-t-il avec les répertoires qui correspondent?). La commande move est un move oldname newname où le nouveau nom est généré en exécutant un shell avec $( subshell here ). What tr does, ...
Hennes

@Hennes: c'est superutilisateur - ai-je vraiment besoin d'entrer dans ce genre de détails? Eh bien, vous y êtes ...
sds

Non. S'il y avait un réel besoin, je n'aurais pas + 1. Et je comprends ce que ça fait. Je pense que c'est bien pour de nombreux autres lecteurs.
Hennes

2
Vous pouvez remplacer le $(echo "$f" | tr ':' '-')par "${f//:/-}"et éviter l'appel de sous-shell, de canal et de programme externe. Je pense que c'est un bashisme, mais hein. Voyez ici .
evilsoup

@evilsoup Effectivement; cela ne fait pas beaucoup de différence pour les petits ensembles de données (et on pourrait favoriser la lisibilité) mais vous seriez surpris de la rapidité avec laquelle quelque chose comme ça s'additionne. Je me suis mordu récemment; la réécriture d'un script de telle sorte que deux simples commandes de massage de chaînes n'étaient plus nécessaires réduisaient facilement le temps d'exécution de 90% ou plus, ce qui sur un grand ensemble de données se traduisait par plusieurs minutes d'exécution de l'horloge murale.
un CVn du

6

Comme indiqué dans un autre post de moi, l' renameoutil pourrait faire l'affaire pour vous. Il vous suffit de taper rename s/:/-/ <files to rename> Ceci remplace chaque deux-points par un tiret dans tous les fichiers que vous nommez à la fin, c'est-à-dire2013-10-*

Voici le lien vers mon autre article


1

Je suis sûr qu'un pro UNIX pourrait le faire avec bash, mais voici ma version rapide et sale avec ruby.

path_to_files = "/home/username/wrongnames/"
filenames = `ls #{path_to_files}`.split
filenames.each do |fn|
  `mv #{path_to_files + fn} #{path_to_files + fn.gsub(/:/, "-")}`
end

définissez path_to_files sur le chemin d'accès à vos fichiers mal nommés. enregistrez le code ci-dessus dans un fichier appelé rename.rb puis:

username@machinename$ ruby rename.rb

@sds fournit une bien meilleure réponse. Dois-je supprimer ma réponse? Je suis nouveau sur stackoverflow.
shupru

1
Non; il a toujours une valeur significative. :)
Blacklight Shining

2
Il y a quelques inconvénients majeurs avec cette réponse, cependant, qui pourraient être pertinents et méritent certainement d'être connus. (Cela pourrait toujours être utile, mais mettez en garde l'emppteur et tout cela.) Principalement, il semble qu'il se cassera mal lorsqu'il rencontrera des noms de fichiers avec des espaces (pas seulement la nouvelle ligne de cas d'échec classique). De plus, même si ce n'était pas pour un espace blanc, vous devez citer le nom de fichier dans l'invocation du shell pour protéger tout autre caractère spécial dans les noms de fichiers contre le traitement par le shell (bien que je ne sache pas exactement comment fonctionne l'opérateur de backtick de Ruby ).
un CVn du

1

Si vous n'avez qu'un ou quelques fichiers, cela peut faire le changement de nom pour vous:

  1. Conservez le modèle du nom de fichier que vous ciblez comme une variable: p="201*".
  2. Stocker le vieux nom de fichier que vous souhaitez renommer: old_name=$(ls | grep $p).
  3. Stockez le nouveau nom de fichier avec les remplacements de caractères nécessaires:

    new_name=$(ls | grep $p | sed 's/:/_/g')        # Using 'sed'
    
                OR
    
    new_name=$(ls | grep $p | tr ':' '_')           # Using 'tr'
    

Nettoyage de bonus :
  a. Si, par souci d'uniformité, vous souhaitez remplacer les tirets (-) ainsi que les deux-points (:) pardes traitsde soulignement (_), vous pouvez le faire:

    new_name=$(ls | grep $p | tr ':-' '_');

  b. Si vous souhaitez que le dernier trait de soulignement (juste avant le .txt) disparaisse également, définissez la new_namevariable comme suit:

    new_name=$(ls | grep $p | tr ':-' '_' | sed 's/_\./\./')
  1. Renommez maintenant votre fichier selon vos besoins: mv $old_name $new_name

         NB: mvéchouera si l'un des noms de fichiers de l'opération de renommage spacess'y trouve. Dans ce cas, enveloppez les variables appropriées entre guillemets, comme:
mv "$old_name" $new_name OU mv $old_name "$new_name" OU mv "$old_name" "$new_name"


One-liners

1a: p="201*"; old_name=$(ls | grep $p); new_name=$(ls | grep $p | sed 's/:/_/g'); mv $old_name $new_name

1b: p="201*"; old_name=$(ls | grep $p); new_name=$(ls | grep $p | tr ':' '_'); mv $old_name $new_name

2: p="201*"; old_name=$(ls | grep $p); new_name=$(ls | grep $p | tr ':-' '_'); mv $old_name $new_name

3: p="201*"; old_name=$(ls | grep $p); new_name=$(ls | grep $p | tr ':-' '_' | sed 's/_\./\./'); mv $old_name $new_name

0

en utilisant renamer :

$ renamer --find ":" --replace "-" *

Je pense que l'installation d'un environnement node.js complet pour simplement renommer des fichiers est un peu trop. renameest un outil préinstallé sur de nombreuses distributions Linux. Mais je pense que pour Windows, cet outil peut être génial.
noggerl

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.