2015-02-19 2 views
0

Допустим, у меня есть следующие файлы в каталоге:Python - усечение неизвестные имена файлов

snackbox_1a.dat 
zebrabar_3z.dat 
cornrows_00.dat 
meatpack_z2.dat 

У меня есть несколько из этих каталогов, в которых все файлы имеют тот же формат, то есть:

snackbox_xx.dat 
zebrabar_xx.dat 
cornrows_xx.dat 
meatpack_xx.dat 

Так что я ЗНАЮ об этих файлах - первый бит (snackbox, zebrabar, cornrows, meatpack). То, что я не знаю, это бит для расширения файла («xx»). Это изменяется как внутри каталога по файлам, так и по каталогам (так что другой каталог может иметь разные значения xx, такие как 12, yy, 2m, 0t, что угодно).

Есть ли способ переименовать все эти файлы или обрезать их все (поскольку xx.dat всегда будет такой же длины), для удобства использования при попытке вызвать их? Например, я хотел бы переименовать их так, чтобы я мог в другом скрипте использовать простой индекс для перехода и найти нужный мне файл (вместо того, чтобы идти в каждый каталог и вытаскивать файл вручную).

Другими словами, я хотел бы изменить имена файлов на:

snackbox.dat 
zebrabar.dat 
cornrows.dat 
meatpack.dat 

Спасибо!

+0

Вы можете найти fnmatch и os.walk полезным –

+0

Давайте предположим, что у вас есть '' snackbox_01.dat' и snackbox_02.dat' они не могут как мне ' snackbox.dat', каков ваш ожидаемый результат здесь? – Vader

ответ

1

Попробуйте re.sub:

import re 
filename = 'snackbox_xx.dat' 
filename_new = re.sub(r'_[A-Za-z0-9]{2}', '', filename) 

Вы должны получить 'snackbox.dat' для filename_new

Это предполагает два символа после «_» являются либо числом, либо в нижнем регистре/прописные буквы, но вы можете выбрать, чтобы расширить классы, включенные в регулярное выражение.

EDIT: включая перемещение и recursive search:

import shutil, re, os, fnmatch 
directory = 'your_path' 

for root, dirnames, filenames in os.walk(directory): 
    for filename in fnmatch.filter(filenames, '*.dat'): 
     filename_new = re.sub(r'_[A-Za-z0-9]{2}', '', filename) 
     shutil.move(os.path.join(root, filename), os.path.join(root, filename_new)) 
+0

Как вы предлагаете найти все файлы, которые, вероятно, составляют около 80 процентов того, что спрашивает OP? –

+0

Только что отредактировано, чтобы включить, что – sharshofski

+0

glob выполняет поиск только по одному каталогу, вам нужно будет рекурсивно проверить –

2

Вы можете использовать shutil.move для перемещения файлов. Чтобы вычислить новое имя файла, вы можете использовать строку split метод Питона:

original_name = "snackbox_12.dat" 
truncated_name = original.split("_")[0] + ".dat" 
0

Это решение переименовывает все файлы в текущем каталоге, которые соответствуют шаблону в вызове функции.

Что делает функция

snackbox_5R.txt >>> snackbox.txt 
snackbox_6y.txt >>> snackbox_0.txt 
snackbox_a2.txt >>> snackbox_1.txt 
snackbox_Tm.txt >>> snackbox_2.txt 

Давайте посмотрим на функции входов и некоторые примеры.

list_of_files_names Это список строк. Где каждая строка является именем файла без части _??.

Примеры:

  • ['snackbox.txt', 'zebrabar.txt', 'cornrows.txt', 'meatpack.txt', 'calc.txt']

  • ['text.dat']

upper_bound=1000 Это целое число. Когда уже будет принято идеальное имя файла, например, snackbox.dat, он будет создавать snackbox_0.dat вплоть до snackbox_9999.dat, если потребуется. Вам не нужно менять значение по умолчанию.


Кодекс

import re 
import os 
import os.path 


def find_and_rename(dir, list_of_files_names, upper_bound=1000): 
    """ 
    :param list_of_files_names: List. A list of string: filname (without the _??) + extension, EX: snackbox.txt 
    Renames snackbox_R5.dat to snackbox.dat, etc. 
    """ 
    # split item in the list_of_file_names into two parts, filename and extension "snackbox.dat" -> "snackbox", "dat" 
    list_of_files_names = [(prefix.split('.')[0], prefix.split('.')[1]) for prefix in list_of_files_names] 

    # store the content of the dir in a list 
    list_of_files_in_dir = os.listdir(dir) 

    for file_in_dir in list_of_files_in_dir: # list all files and folders in current dir 
     file_in_dir_full_path = os.path.join(dir, file_in_dir) # we need the full path to rename to use .isfile() 
     print() # DEBUG 
     print('Is "{}" a file?: '.format(file_in_dir), end='') # DEBUG 
     print(os.path.isfile(file_in_dir_full_path)) # DEBUG 
     if os.path.isfile(file_in_dir_full_path): # filters out the folder, only files are needed 

      # Filename is a tuple containg the prefix filename and the extenstion 
      for file_name in list_of_files_names: # check if the file matches on of our renaming prefixes 

       # match both the file name (e.g "snackbox") and the extension (e.g "dat") 
       # It find "snackbox_5R.txt" by matching "snackbox" in the front and matching "dat" in the rear 
       if re.match('{}_\w+\.{}'.format(file_name[0], file_name[1]), file_in_dir): 
        print('\nOriginal File: ' + file_in_dir) # printing this is not necessary 
        print('.'.join(file_name)) 

        ideal_new_file_name = '.'.join(file_name) # name might already be taken 
        # print(ideal_new_file_name) 
        if os.path.isfile(os.path.join(dir, ideal_new_file_name)): # file already exists 
         # go up a name, e.g "snackbox.dat" --> "snackbox_1.dat" --> "snackbox_2.dat 
         for index in range(upper_bound): 
          # check if this new name already exists as well 
          next_best_name = file_name[0] + '_' + str(index) + '.' + file_name[1] 

          # file does not already exist 
          if os.path.isfile(os.path.join(dir,next_best_name)) == False: 
           print('Renaming with next best name') 
           os.rename(file_in_dir_full_path, os.path.join(dir, next_best_name)) 
           break 

          # this file exist as well, keeping increasing the name 
          else: 
           pass 

        # file with ideal name does not already exist, rename with the ideal name (no _##) 
        else: 
         print('Renaming with ideal name') 
         os.rename(file_in_dir_full_path, os.path.join(dir, ideal_new_file_name)) 


def find_and_rename_include_sub_dirs(master_dir, list_of_files_names, upper_bound=1000): 
    for path, subdirs, files in os.walk(master_dir): 
     print(path) # DEBUG 
     find_and_rename(path, list_of_files_names, upper_bound) 


find_and_rename_include_sub_dirs('C:/Users/Oxen/Documents/test_folder', ['snackbox.txt', 'zebrabar.txt', 'cornrows.txt', 'meatpack.txt', 'calc.txt'])