2010-11-10 9 views
6

J'ai un dossier complet de fichiers d'image tels quechangement de nom en vrac de fichiers basés sur recherche

  • 1500000704_full.jpg
  • 1500000705_full.jpg
  • 1500000711_full.jpg
  • 1500000712_full.jpg
  • 1500000714_full.jpg
  • 1500000744_full.jpg
  • 1500000745_full.jpg
  • 1500000802_full.jpg
  • 1500000803_full.jpg

J'ai besoin de renommer les fichiers basés sur une recherche à partir d'un fichier texte qui contient des entrées telles que,

  • SH103239 1500000704
  • SH103240 1500000705
  • SH103241 1500000711
  • SH103242 1500000712
  • SH103243 1500000714
  • SH103244 1500000744
  • SH103245 1500000745
  • SH103252 1500000802
  • SH103253 1500000803
  • SH103254 1500000804

, je veux donc les fichiers d'image à renommer,

  • SH103239_full.jpg
  • SH103240_full.jpg
  • SH103241_full.jpg
  • SH103242_full.jpg
  • SH103243_full.jpg
  • SH103244_full.jpg
  • SH103245_full.jpg
  • SH103252_full.jpg
  • SH103253_full .jpg
  • SH103254_full.jpg

Comment puis-je faire ce travail le plus facile? N'importe qui peut m'écrire une commande rapide ou un script qui peut le faire pour moi s'il vous plaît? J'ai beaucoup de ces fichiers d'image et le changement manuel n'est pas réalisable.

Je suis sur Ubuntu mais en fonction de l'outil, je peux passer à Windows si besoin est. Idéalement j'aimerais l'avoir dans le script bash pour que je puisse en apprendre plus ou perl ou python.

Merci

EDIT: avons dû changer les noms de fichiers

+0

Y a-t-il le même nombre d'entrées dans le fichier de recherche que de fichiers image? –

+0

Il y a plus d'images que le nombre d'entrées dans le fichier – bcrawl

+0

Ensuite, itérer sur les entrées est plus efficace que d'itérer sur les fichiers. –

Répondre

6

Voici un simple script Python 2 pour le renommer.

#!/usr/bin/env python 

import os 

# A dict with keys being the old filenames and values being the new filenames 
mapping = {} 

# Read through the mapping file line-by-line and populate 'mapping' 
with open('mapping.txt') as mapping_file: 
    for line in mapping_file: 
     # Split the line along whitespace 
     # Note: this fails if your filenames have whitespace 
     new_name, old_name = line.split() 
     mapping[old_name] = new_name 

suffix = '_full' 

# List the files in the current directory 
for filename in os.listdir('.'): 
    root, extension = os.path.splitext(filename) 
    if not root.endswith(suffix): 
     # File doesn't end with this suffix; ignore it 
     continue 
    # Strip off the number of characters that make up suffix 
    stripped_root = root[:-len(suffix)] 
    if stripped_root in mapping: 
     os.rename(filename, ''.join(mapping[stripped_root] + suffix + extension)) 

Différents bits du script sont codés en dur, ce qui ne devrait vraiment pas être le cas. Ceux-ci incluent le nom du fichier de mappage (mapping.txt) et le suffixe de nom de fichier (_full). Ceux-ci pourraient vraisemblablement être passés en arguments et interprétés en utilisant sys.argv.

+0

Salut, pouvez-vous me donner quelques détails sur la façon dont je devrais exécuter ce script. Quand je cours cela, rien ne se passe. Mon fichier mapping.txt est comme dans le post original ci-dessus. Toutes les astuces seraient super. – bcrawl

+0

Désolé, tant pis. Je courais un autre script. Cela fonctionne très bien. Merci. – bcrawl

+0

+1 Bien et simple. – hughdbrown

1

Lire dans le fichier texte, créez un hachage avec le nom du fichier en cours, donc files['1500000704'] = 'SH103239' et ainsi de suite. Parcourez ensuite les fichiers du répertoire en cours, récupérez le nouveau nom du fichier et renommez-le.

+0

Indiquer un tableau avec une chaîne? – tchrist

+0

non, seulement python. bien que, ils sont appelés des tableaux associatifs ... – muhmuhten

+0

Voir la réponse de Wesley pour le code semblable à ce que je n'avais pas encore écrit. –

5

Cela fonctionne pour votre problème:

#!/usr/bin/perl 
while (<DATA>) { 
    my($new, $old) = split; 
    rename("$old.jpg", "$new.jpg") 
     || die "can't rename "$old.jpg", "$new.jpg": $!"; 
} 
__END__ 
SH103239 1500000704 
SH103240 1500000705 
SH103241 1500000711 
SH103242 1500000712 
SH103243 1500000714 
SH103244 1500000744 
SH103245 1500000745 
SH103252 1500000802 
SH103253 1500000803 
SH103254 1500000804 

Passer au ARGV de DATA lire les lignes d'un fichier d'entrée particulier.

Normalement, pour la masse des opérations renomme, j'utilise quelque chose comme ceci:

#!/usr/bin/perl 
# rename script by Larry Wall 
# 
# eg: 
#  rename 's/\.orig$//' *.orig 
#  rename 'y/A-Z/a-z/ unless /^Make/' * 
#  rename '$_ .= ".bad"' *.f 
#  rename 'print "$_: "; s/foo/bar/ if <STDIN> =~ /^y/i' * 
#  find /tmp -name '*~' -print | rename 's/^(.+)~$/.#$1/' 

($op = shift) || die "Usage: rename expr [files]\n"; 

chomp(@ARGV = <STDIN>) unless @ARGV; 

for (@ARGV) { 
    $was = $_; 
    eval $op; 
    die if [email protected]; # means eval `failed' 
    rename($was,$_) unless $was eq $_; 
} 

J'ai une version plus complète, mais cela devrait suffire.

+0

pouvons-nous avoir la version la plus complète que vous avez pour notre utilisation. cela peut être utile pour d'autres utilisateurs ... de quoi d'autre votre script peut faire. comme mkdir etc. merci. – ihightower

+0

@ihightower Voir [ici] (http://training.perl.com/scripts/rename). – tchrist

1
#!/bin/bash 

for FILE in *.jpg; do 
    OLD=${FILE%.*} # Strip off extension. 
    NEW=$(awk -v "OLD=$OLD" '$2==OLD {print $1}' map.txt) 
    mv "$OLD.jpg" "$NEW.jpg" 
done 
2

Une réécriture de l'utilisation des générateurs de Wesley:

import os, os.path 

with open('mapping.txt') as mapping_file: 
    mapping = dict(line.strip().split() for line in mapping_file) 

rootextiter = ((filename, os.path.splitext(filename)) for filename in os.listdir('.')) 
mappediter = (
    (filename, os.path.join(mapping[root], extension)) 
    for filename, root, extension in rootextiter 
    if root in mapping 
) 
for oldname, newname in mappediter: 
    os.rename(oldname, newname) 
+0

Nasty. Peut-être que je n'ai pas fait de python assez longtemps (quatre ou cinq ans!), Mais c'est complètement illisible pour moi. –

+0

@Graeme Perrow: lire David Beazley sur les générateurs, a changé ma vie. http://www.dabeaz.com/generators/ – hughdbrown

1

Ceci est très simple à faire dans Bash en supposant qu'il ya une entrée dans le fichier de recherche pour chaque fichier et chaque fichier a une entrée de recherche.

#!/bin/bash 
while read -r to from 
do 
    if [ -e "${from}_full.jpg" ] 
    then 
     mv "${from}_full.jpg" "${to}_full.jpg" 
    fi 
done < lookupfile.txt 

Si le fichier de recherche contient beaucoup plus d'entrées que de fichiers, cette approche peut s'avérer inefficace. Si l'inverse est vrai, une approche qui itère sur les fichiers peut être inefficace. Cependant, si les nombres sont proches, cela peut être la meilleure approche, car il n'est pas nécessaire de faire des recherches.

Si vous préférez une version de recherche qui est-Bash pur:

#!/bin/bash 
while read -r to from 
do 
    lookup[from]=$to 
done < lookupfile.txt 

for file in *.jpg 
do 
    base=${file%*_full.jpg} 
    mv "$file" "${lookup[base]}_full.jpg" 
done 
0

Voici un petit hack amusant:

paste -d " " lookupfile.txt lookupfile.txt | cut -d " " -f 2,3 | sed "s/\([ ]\|$\)/_full.jpg /g;s/^/mv /" | sh 
2

I modifié le code de Wesley à travailler pour ma situation. J'ai eu un fichier de mappage "sort.txt" qui consistait en différents fichiers .pdf et numéros pour indiquer l'ordre dans lequel je les veux en fonction d'une sortie de la manipulation DOM à partir d'un site Web. Je voulais combiner tous ces fichiers PDF séparés en un seul fichier pdf, mais je voulais conserver le même ordre dans lequel ils se trouvent qu'ils sont sur le site. Je voulais donc ajouter des numéros en fonction de leur emplacement dans un menu de navigation.

1054 spellchecking.pdf 
1055 using-macros-in-the-editor.pdf 
1056 binding-macros-with-keyboard-shortcuts.pdf 
1057 editing-macros.pdf 
1058 etc........ 

Voici le code que je suis venu avec:

import os, sys 

# A dict with keys being the old filenames and values being the new filenames 
mapping = {} 

# Read through the mapping file line-by-line and populate 'mapping' 
with open('sort.txt') as mapping_file: 
    for line in mapping_file: 

     # Split the line along whitespace 
     # Note: this fails if your filenames have whitespace 
     new_name, old_name = line.split() 
     mapping[old_name] = new_name 


# List the files in the current directory 
for filename in os.listdir('.'): 
    root, extension = os.path.splitext(filename) 

    #rename, put number first to allow for sorting by name and 
    #then append original filename +e extension 
    if filename in mapping: 
     print "yay" #to make coding fun 
     os.rename(filename, mapping[filename] + filename + extension) 

Je n'ai pas eu un suffixe comme _Full donc je ne l'ai pas besoin de ce code. A part ça c'est le même code, je n'ai jamais vraiment touché à Python donc c'était une bonne expérience d'apprentissage pour moi.

0
import os,re,sys 

mapping = <Insert your mapping here> #Dictionary Key value entries (Lookup) 

for k,v in mapping: 
    for f in os.listdir("."): 
     if re.match('1500',f): #Executes code on specific files 
      os.rename(f,f.replace(k,v)) 
Questions connexes