5

Hi there i've been trying to adapt this to my needs but I'm just a newbe in python, I have a csv file with multiple columns and rows, important columns are 1 = old name of file, and 2 = new name of file, so I need to go the directory where the files listed in csv file are and rename them to the new name of column 2, as I say I've tried many things without success, I paste the last code I've made so you have an idea:

import os, unicodecsv as csv, sys

IDs = {}

#open and store the csv file
with open('documentos_corpus_ladino.csv','rb') as csvfile:
        timeReader = csv.reader(csvfile, delimiter = ',')

        # build a dictionary with the associated IDs
        for row in timeReader:
              IDs[ row[0] ] = row[1]

# #get the list of files
path = 'txt_orig/'
tmpPath = 'txt_tmp/'
for filename in os.listdir('txt_orig/'):
    oldname = filename
    newname = filename.replace(oldname, csvfile.next().rstrip().split(",")[1])
    os.rename(path + filename, tmpPath + newname)

Thanks a lot.

Community
  • 1
  • 1
Andrés Chandía
  • 999
  • 1
  • 16
  • 32
  • I believe in the ID dictionary, you have already mapped your old file names to the new file names. So, you should just iterate over that dictionary and rename the files. Why do you need to first list the files using os.listdir()? – Chandranshu Nov 17 '13 at 17:10
  • If you got the answer from any of the below please vote and accept it. or else comment saying what you exactly need. – Sravan K Ghantasala Nov 18 '13 at 02:42

4 Answers4

5

This will rename each matching file, and report any errors trying to rename. It will not attempt to move non-existent files.

import os, unicodecsv as csv
# open and store the csv file
IDs = {}
with open('documentos_corpus_ladino.csv','rb') as csvfile:
    timeReader = csv.reader(csvfile, delimiter = ',')
    # build dictionary with associated IDs
    for row in timeReader:
        IDs[row[0]] = row[1]
# move files
path = 'txt_orig/'
tmpPath = 'txt_tmp/'
for oldname in os.listdir(path):
    # ignore files in path which aren't in the csv file
    if oldname in IDs:
        try:
            os.rename(os.path.join(path, oldname), os.path.join(tmpPath, IDs[oldname]))
        except:
            print 'File ' + oldname + ' could not be renamed to ' + IDs[oldname] + '!'
Pi Marillion
  • 4,465
  • 1
  • 19
  • 20
  • Thanks a lot it works great. Anyway how could I copy the files instead of moving them, I mean keeping the original file? – Andrés Chandía Nov 18 '13 at 16:53
  • 1
    @AndrésChandía Sure, just use `shutil.copy(source, dest)` instead of `os.rename(source, dest)` to copy file instead of moving. – Pi Marillion Nov 18 '13 at 17:01
  • Don't work, for all the files it says "could not be renamed to", this is what i put: shutil.copy(os.path.join(path, oldname), os.path.join(destPath, IDs[oldname])) – Andrés Chandía Nov 18 '13 at 17:07
  • 1
    That sounds like a permissions issue, either with the file being replaced or the file being copied. If it's with the file being copied, then using `shutil.copyfile`, which doesn't copy permissions, may work. – Pi Marillion Nov 18 '13 at 23:29
  • Sorry, still not working, the code: IDs = {} with open('documentos_corpus_ladino.csv','rb') as csvfile: timeReader = csv.reader(csvfile, delimiter = ',') for row in timeReader: IDs[row[0]] = row[1] path = 'txt_orig/' destPath = 'txt/' for oldname in os.listdir(path): if oldname in IDs: try: shutil.copyfile(os.path.join(path, oldname), os.path.join(destPath, IDs[oldname])) except: print 'File ' + oldname + ' could not be renamed to ' + IDs[oldname] + '!' – Andrés Chandía Nov 19 '13 at 09:52
  • Ok, all the problem was that I had to import shutil also, thanks a lot – Andrés Chandía Nov 19 '13 at 16:49
2

You should make use of the dictionary IDs that you created from your CSV:

for filename in os.listdir(path):
    oldname = filename
    newname = IDs[oldname]
    os.rename(path + filename, tmpPath + newname)

But you probably should use some kind of error checking.. (Edit As the other answers have pointed out it's best to use also os.path.join) Maybe something along these lines:

failed = []
for oldname in os.listdir(path):
    try:
        old = os.path.join(path, oldname)
        new = os.path.join(tmpPath, IDs[oldname])
        os.rename(old, new)
    except KeyError, OSError:
        failed.append(oldname)

print failed
  • Thanks a lot, I got some issues though with both codes. If there is a file at the input directory that is not in the csv file then the script stops, also when the file name contains any character like ñ or ç – Andrés Chandía Nov 18 '13 at 16:46
  • @AndrésChandía: You're right, I now see that my code fails with Unicode characters if you use Python 2. But I think the `try` block should take care of that and the script should at least finish.. Hmm weird. –  Nov 18 '13 at 17:20
1

You're iterating on the file and store old and new names in IDs but don't use it and just try to read further from the file (which will fail obviously since you've already read the whole file by that time). IOW you should use your IDs dict to get new names (using the oldname as key) instead, ie:

path = 'txt_orig' # no trailing slash required
tmpPath = 'txt_tmp' # idem
for filename in os.listdir(path):
    try:
       newname = IDs[filename]
    except KeyError:
       print "no new name for '%s'" % filename
       continue
    else:     
        os.rename(os.path.join(path, filename), os.path.join(tmpPath, newname))

Now there's a much simpler solution: just rename the files as you iterate on the csv file:

path = 'txt_orig'
tmp_path = 'txt_tmp'

with open('documentos_corpus_ladino.csv','rb') as csvfile:
    reader = csv.reader(csvfile, delimiter = ',')
    for row in reader:
       oldname = os.path.join(path, row[0])
       if os.path.exists(oldname):
           newname = os.path.join(tmp_path, row[1])
           os.rename(oldname, newname)
           print >> sys.stderr, "renamed '%s' to '%s'" % (oldname, newname)
       else:
           print >> sys.stderr, "file '%s' not found" % oldname
bruno desthuilliers
  • 75,974
  • 6
  • 88
  • 118
  • Thanks a lot, your first code give error when a file name contains characters like ñ or ç, but the second one works great. Anyway how could I copy the files instead of moving them, I mean keeping the original file? – Andrés Chandía Nov 18 '13 at 16:52
0

This is what I came up with after not having success using the above snippets. You could do this without pandas but I also needed to do formatting and remove some duplicate values from my data so pandas made my life easier.

import os
import pandas as pd


csv_name = "/home/your_filename.csv"
#parent_dir is the directory that has the folders you want to rename
parent_dir = "/path/to/folder"
df  =  pd.read_csv(csv_name)

list_oldnames = df['Old_Name'].astype(str).to_list()

list_newnames = df['New_Name'].astype(str).to_list()

for folder in os.listdir(parent_dir):
    for oldname, newname in zip(list_oldnames, list_newnames):
        if str(oldname) == str(folder):
            try:
                os.rename(os.path.join(parent_dir, oldname), os.path.join(parent_dir, newname))
            except:
                print("Could not rename "+ str(os.path.join(parent_dir, oldname)) )