2016-01-01 6 views
1

У меня есть файл CSV, состоящий из двух столбцов.Как найти и заменить список имен файлов из списка

Один столбец - это старое имя файла, а другое - новое имя файла.

Я хочу заменить фактические имена файлов в папке новыми именами файлов.

Я смотрел экстенсивно, но не могу узнать, как это сделать.

Мой входной файл состоит в следующем:

New Old 
Dys.FSA_BB_NEW_0204_Sp_5_HBG_fq.gz.res Cfda 
Dys.FSC_Sp_BB_LC_0028_R1_30_HBG_fq.gz.res Cyffa 
Dys_BB_NEW_0177_Sp_FSD.5_HBG_fq.gz.res Cyfsaff 
Dys_FSE.BB_AM_0104_Sp_5_HBG_fq.gz.res afffa 
Dys_FSF.AM_0068_Sp_5_HBG_fq.gz.res Cvdsd 
Dys_FSG.BB_LC_261_Sp_15_HBG_fq.gz.res vsvds0 
Dys_FSH.BB_LC_0047_Sp_10_HBG_fq.gz.res Cyto_vds.0 
Dys_FastB_BB_LC_0028_Sp_15_HBG_fq.gz.res Cvsv 
Dys_FSA_OC_AH_255_E_B1_Biopsy_30_LBG_fq.gz.res AneupvsvEFS 
Dys_FSC_OC_UC_025_E_B1_Biopsy_25_LBG_fq.gz.res vdvsupDysplasticBEFS 
Dys_FSD_BB_POR_0028_Biopsy_30_HBG_fq.gz.res 24vdvdS 
Dys_FSH_BB_NEW_0097_Biopsy_70_HBG_fq.gz.res Avdsgf3 
Dys_FSI_BB_AM_0003_Biopsy_60_LBG_fq.gz.res AnfdsfdsFS 

Я полагаю, я должен создать массив хэшей первого из CSV, используя что-то вроде этого:

require 'csv' 
csv_data = CSV.read '/Users/sebastianzeki/Desktop/tbb.csv' 
headers = csv_data.shift.map {|i| i.to_s } 
string_data = csv_data.map {|row| row.map {|cell| cell.to_s } } 
array_of_hashes = string_data.map {|row| Hash[*headers.zip(row).flatten] } 

Это дает мне:

[{"New"=>"Dys.FSA_BB_NEW_0204_Sp_5_HBG_fq.gz.res", "Old"=>"Cfda"}, {"New"=>"Dys.FSC_Sp_BB_LC_0028_R1_30_HBG_fq.gz.res", "Old"=>"Cyffa"}, {"New"=>"Dys_BB_NEW_0177_Sp_FSD.5_HBG_fq.gz.res", "Old"=>"Cyfsaff"}, {"New"=>"Dys_FSE.BB_AM_0104_Sp_5_HBG_fq.gz.res", "Old"=>"afffa"}, {"New"=>"Dys_FSF.AM_0068_Sp_5_HBG_fq.gz.res", "Old"=>"Cvdsd"}, {"New"=>"Dys_FSG.BB_LC_261_Sp_15_HBG_fq.gz.res", "Old"=>"vsvds0"}, {"New"=>"Dys_FSH.BB_LC_0047_Sp_10_HBG_fq.gz.res", "Old"=>"Cyto_vds.0"}, {"New"=>"Dys_FastB_BB_LC_0028_Sp_15_HBG_fq.gz.res", "Old"=>"Cvsv"}, {"New"=>"Dys_FSA_OC_AH_255_E_B1_Biopsy_30_LBG_fq.gz.res", "Old"=>"AneupvsvEFS"}, {"New"=>"Dys_FSC_OC_UC_025_E_B1_Biopsy_25_LBG_fq.gz.res", "Old"=>"vdvsupDysplasticBEFS"}, {"New"=>"Dys_FSD_BB_POR_0028_Biopsy_30_HBG_fq.gz.res", "Old"=>"24vdvdS"}, {"New"=>"Dys_FSH_BB_NEW_0097_Biopsy_70_HBG_fq.gz.res", "Old"=>"Avdsgf3"}, {"New"=>"Dys_FSI_BB_AM_0003_Biopsy_60_LBG_fq.gz.res", "Old"=>"AnfdsfdsFS"}] 

Итак, как мне преобразовать фактическое имя файла в папку в новую (в той же папке)?

отредактирован с помощью ответа

csv_lines = CSV.open('/Users/sebastianzeki/Desktop/tbb.csv', 
        headers: true, 
        col_sep: "\b") 


filenames = Dir.glob("/Users/sebastianzeki/myfolder/*") 

csv_lines.each do |row| 
    old_name = row['Old'] 
    new_name = row['New'] 
    filenames.each do |filename| 
    File.rename(old_name,new_name) 
    end 
end 
+1

Вы посмотрели на [Как переименовать файл в Ruby] (http://stackoverflow.com/questions/5530479/how-to-rename-a-file-in-ruby)? Что вы подразумеваете под 'convert the actual filename'? –

+0

Да, я это видел. Проблема в том, что я хочу попытаться преобразовать старое имя файла с новым именем файла на основе хеша, который я поставил в вопросе. Фактическое имя файла - это имя файла (в отличие от простого преобразования старого имени в хэш в новое имя в хеше). –

+0

Какой смысл «редактировать с помощью ответа @ tuo» (что неверно, кстати, поскольку он неоднократно переименовывает «old_name' в' new_name' для каждой «строки»)? Редактирование должно состоять только в том, чтобы прояснить вопрос, а иногда и показать, что вы пробовали. –

ответ

1

Я немного запутался, а ваш входной файл, но при условии, CSV файл с разделением запятыми и без каких-либо заголовков вы могли бы сделать это:

rename.csv (new_file, old_file)

foo_file_one,file_one 
foo_file_two,file_two 

Предполагая rename.csv и ваши файлы будут переименованы в той же папке

require 'csv' 

rename_list = CSV.parse(File.read('rename.csv')) 

rename_list.each do |new, old| 
    File.rename(old, new) rescue '' 
end 

Однако это означает, что ваш переименовать.CSV не может иметь пробелы, но использует запятые

+0

Спасибо. Означает ли это, что File.rename увидит старое имя файла, а затем заменит его соответствующим новым именем файла, с которым он «сопряжен»? –

+0

Да, это займет старое имя в csv и заменит его новым именем.Если файл не существует, он спасет его в этом случае (если вы этого не сделаете, он предоставит SystemCallError, если файл не существует). –

2

@ Его в Вы можете загрузить CSV в CSV :: Ряды так:

csv_lines = CSV.open(input_file_name, 
        headers: true, 
        col_sep: "\b") 

Это даст вам все Csv строки с заголовками, вы могут повторять эти строки следующим образом:

path = '/your/dir/path/' 

csv_lines.each do |row| 
    old_name = row['Old'] 
    new_name = row['New'] 

    #TODO: find the file with the old name and update it to the new one 

    #EDIT: it can be done like this: 
    File.rename(path + old_name, path + new_name) 
end 

Я думаю, вы уже знаете, как выполнять работу по переименованию. :)

Редактировать: я добавил переименование в свой код. Не нужно сканировать папку в каждом цикле. Вам просто нужно найти один файл и переименовать его за раз.

PS. Вы можете добавить обработчик исключений в цикле, если в вашем входном файле отсутствует файл.

+0

Хммм. На самом деле это работа переименования, которую я не могу понять. У меня было что-то в этом вопросе, возможно, это сработает? –

+0

Не уверен, что я могу разобраться, как перебирать папку с именами файлов в ней и находить старое имя? Надеюсь, это имеет смысл с моего кода обновления –

1

Предположим, что ваш файл содержит только эти пять строк:

my_data = <<_ 
    New Old 
Dys.FSA_BB_NEW_0204_Sp_5_HBG_fq.gz.res Cfda 
Dys.FSC_Sp_BB_LC_0028_R1_30_HBG_fq.gz.res Cyffa 
Dys_BB_NEW_0177_Sp_FSD.5_HBG_fq.gz.res Cyfsaff 
Dys_FSE.BB_AM_0104_Sp_5_HBG_fq.gz.res afffa 
_ 

Давайте создадим файл

FName = "my_file.txt" 

в пустом каталоге:

File.write(FName, my_data) 
    #=> 201 

Dir.entries(".") 
    #=> [".", "..", "my_file.txt"] 

Для тестирования создадим (пустые) файлы, заданные массивом:

arr = ["Cfda", "Cyffa", "Cyfsaff"] 

(но не «afffa») в том же каталоге:

arr.each { |name| File.write(name,'') } 

Dir.entries(".") 
    #=> [".", "..", "Cfda", "Cyffa", "Cyfsaff", "my_file.txt"] 

Теперь мы можем прочитать файл FName линия за линией в массив, отбрасывать заголовок и переименовывать файлы в текущий каталог с именами, заданных по «старому имени»:

File.readlines(FName)[1..-1].each do |s| 
    new, old = s.chomp.split 
    File.rename(old, new) if File.exist?(old) 
end 

Dir.entries(".") 
    #=> [".", "..", "Dys.FSA_BB_NEW_0204_Sp_5_HBG_fq.gz.res", 
    # "Dys.FSC_Sp_BB_LC_0028_R1_30_HBG_fq.gz.res", 
    # "Dys_BB_NEW_0177_Sp_FSD.5_HBG_fq.gz.res", "my_file.txt"] 

Вы можете использовать CSV методы класса, но нет необходимости делать это.

Если вы хотите сделать это в каталоге, который не является текущим каталогом, либо измените текущий каталог, либо добавьте путь к именам файлов.

+0

Спасибо за хороший ответ и очень приятно объяснили. @ Ответ Nabeelas работал, поэтому получил тик, но ваш тоже был поддержан –

Смежные вопросы