-
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Find_and_replace.py
257 lines (222 loc) · 16.9 KB
/
Find_and_replace.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
print('''
Python3-скрипт переименования папок и файлов,
а также поиска и замены подстрок в текстах.
Автор: Платон Быкадоров (platon.work@gmail.com), 2018-2019.
Версия: V1.1.
Лицензия: GNU General Public License version 3.
Поддержать проект: https://money.yandex.ru/to/41001832285976
Простое руководство по установке среды разработки и запуску скриптов:
github.com/PlatonB/bioinformatic-python-scripts#Установка-среды-разработки
Если нужно ввести пробел или табуляцию в качестве
элемента заменяемой подстроки, то не обязательно использовать
управляющий символ: достаточно нажать соответствующую клавишу.
''')
def check_input(var):
'''
Проверка правильности ввода пользователем опций.
В случае ошибки работа программы завершится.
'''
if var != 'in_current_folder' and var != 'deep' and var != 'no' and var != 'n':
print(f'{var} - недопустимая опция')
sys.exit()
def rename(rename_fs_objs_pattern, rename_fs_objs_repl, src_fs_obj_name, src_higher_dir_path, src_fs_obj_path):
'''
Для переименования файлов и папок производится
идентичная последовательность действий: и для
одних, и для других формируется новое название,
потом абсолютный путь с этим новым названием, а
затем изменение применяется уже на уровне ФС ОС.
'''
trg_fs_obj_name = re.sub(rename_fs_objs_pattern, rename_fs_objs_repl, src_fs_obj_name)
trg_fs_obj_path = os.path.join(src_higher_dir_path, trg_fs_obj_name)
os.rename(src_fs_obj_path, trg_fs_obj_path)
def text_processing(src_file_path, src_file_name, num_of_headers, trg_dir_path, rename_ctrl_h_pattern, rename_ctrl_h_repl):
'''
Создание конечного файла и сохранение
в него отредактированного текста.
'''
with open(src_file_path) as src_file_opened:
print('Производится поиск и замена в', src_file_name)
#Формирование списка хэдеров.
#Курсор смещается к началу основной части текста.
headers = [src_file_opened.readline().split('\n')[0] for header_index in range(num_of_headers)]
#Конструирование имени конечного файла, создание
#самого файла и прописывание туда хэдеров.
src_file_base = '.'.join(src_file_name.split('.')[:-1])
src_file_ext = '.' + src_file_name.split('.')[-1]
trg_file_name = src_file_base + '_edtd' + src_file_ext
with open(os.path.join(trg_dir_path, trg_file_name), 'w') as trg_file_opened:
for header in headers:
trg_file_opened.write(header + '\n')
#Работа с основной частью текста.
for line in src_file_opened:
#Замена подстроки.
edited_line = re.sub(rename_ctrl_h_pattern, rename_ctrl_h_repl, line).split('\n')[0]
#Прописывание обработанной строки в конечный файл.
trg_file_opened.write(edited_line + '\n')
####################################################################################################
import os, sys, re
src_top_dir_path = input('Путь к исходной верхней папке: ')
rename_dirs = input('''\nПереименовывать папки?
[in_current_folder|deep|no(|n)]: ''')
check_input(rename_dirs)
if rename_dirs == 'in_current_folder' or rename_dirs == 'deep':
rename_dirs_pattern = input('''\nЗаменяемая часть названий папок
(четырьмя пробелами с каждой стороны
выделен пример регулярного выражения)
[Whole_Blood|2018| ^ |...]: ''')
rename_dirs_repl = input('\nНа что заменять?: ')
rename_files = input('''\nПереименовывать файлы?
[in_current_folder|deep|no(|n)]: ''')
check_input(rename_files)
if rename_files == 'in_current_folder' or rename_files == 'deep':
rename_files_pattern = input('''\nЗаменяемая часть названий файлов
(четырьмя пробелами с каждой стороны
выделен пример регулярного выражения)
[chr14|bed| (?:tab)|(?:[ct]sv) |...]: ''')
rename_files_repl = input('\nНа что заменять?: ')
ctrl_h = input('''\nНайти и заменить подстроку в файлах?
[in_current_folder|deep|no(|n)]: ''')
check_input(ctrl_h)
if ctrl_h == 'in_current_folder' or ctrl_h == 'deep':
trg_top_dir_path = input('\nПуть к верхней папке для конечных файлов: ')
if trg_top_dir_path == src_top_dir_path or trg_top_dir_path.startswith(src_top_dir_path + os.sep) == True:
print('''Конечная папка не должна быть той же, что
и исходная, или находиться внутри исходной''')
sys.exit()
num_of_headers = input('''\nКоличество не обрабатываемых строк
в начале каждого исходного текста
(игнорирование ввода ==> хэдеров/шапок в текстах нет)
[0(|<enter>)|1|2|...]: ''')
if num_of_headers == '':
num_of_headers = 0
else:
num_of_headers = int(num_of_headers)
rename_ctrl_h_pattern = input('''\nЗаменяемая часть текстов
(четырьмя пробелами с каждой стороны
выделен пример регулярного выражения)
[,|:| (?<=Type=).+?(?=,) |...]: ''')
rename_ctrl_h_repl = input('\nНа что заменять?: ')
if 'rename_dirs_pattern' in locals() or 'rename_files_pattern' in locals():
are_you_sure = input('''\nЧасть выбранных Вами действий
приведёт к потере оригинальных названий.
Вы уверены, что хотите запустить выполнение?
[yes(|y)|no(|n)]: ''')
if are_you_sure != 'yes' and are_you_sure != 'y':
print('Работа программы прервана.')
sys.exit()
##Выбор пользователя - переименовывать объекты файловой системы
##(далее - ФС) только в пределах непосредственно папки верхнего уровня.
if rename_dirs == 'in_current_folder' or rename_files == 'in_current_folder':
#Сохранение в список любых объектов ФС - как
#папок, так и файлов - находящихся на начальном
#уровне вложенности верхней исходной папки.
#Перебор этих объектов и получение
#абсолютного пути к каждому из них.
src_fs_obj_names = os.listdir(src_top_dir_path)
for src_fs_obj_name in src_fs_obj_names:
src_fs_obj_path = os.path.join(src_top_dir_path, src_fs_obj_name)
#Определение типа объекта ФС - папка это или файл.
#Выполнение переименования, процесс которого описан
#в строках документации к соответствующей функции.
if rename_dirs == 'in_current_folder' and os.path.isdir(src_fs_obj_path) == True:
rename(rename_dirs_pattern,
rename_dirs_repl,
src_fs_obj_name,
src_top_dir_path,
src_fs_obj_path)
if rename_files == 'in_current_folder' and os.path.isfile(src_fs_obj_path) == True:
rename(rename_files_pattern,
rename_files_repl,
src_fs_obj_name,
src_top_dir_path,
src_fs_obj_path)
##Выбор пользователя - переименовывать
##объекты ФС всех уровней вложенности
##относительно верхней исходной папки.
elif rename_dirs == 'deep' or rename_files == 'deep':
#При проходе по объектам ФС всех уровней вложенности функцией
#os.walk происходит автоматическое определение их типов, а также
#формирование удобной для скриптовой обработки структуры данных.
#Каждый элемент этой структуры - путь к одной из папок, список
#путей к подпапкам этой папки и список файлов данной папки.
#Чтобы не пилить сук, на котором сидишь, переименовывать следует
#начинать с самых глубоких папок и заканчивать самыми верхними.
#В противном случае, будут меняться пути к ещё необработанным
#более глубоким объектам ФС и теряться возможность обращения
#к таковым (в os.walk-структуре-то хранятся ещё старые пути!).
#Чтобы переименовывать в последовательности от глубоких папок к
#верхним, пути к папкам сортируются по их длине в обратном порядке.
for src_parent_dir_path, src_dir_names, src_file_names in sorted(os.walk(src_top_dir_path),
key=lambda level: len(level[0]),
reverse=True):
#В зависимости от решения пользователя, перебираем в текущей
#папке либо папки, либо файлы, либо по очереди и то, и то.
#Переименовываем с помощью подробно описанной выше функции.
if rename_dirs == 'deep':
for src_dir_name in src_dir_names:
src_dir_path = os.path.join(src_parent_dir_path, src_dir_name)
rename(rename_dirs_pattern,
rename_dirs_repl,
src_dir_name,
src_parent_dir_path,
src_dir_path)
if rename_files == 'deep':
for src_file_name in src_file_names:
src_file_path = os.path.join(src_parent_dir_path, src_file_name)
rename(rename_files_pattern,
rename_files_repl,
src_file_name,
src_parent_dir_path,
src_file_path)
##Выбор пользователя - производить поиск и замену подстрок
##в файлах, находящихся в папке лишь одного - верхнего уровня.
##В результате работы переименовательной части скрипта,
##файлы могут быть уже с новыми названиями, поэтому
##формируем список содержимого директории заново.
if ctrl_h == 'in_current_folder':
src_fs_obj_names = os.listdir(src_top_dir_path)
for src_fs_obj_name in src_fs_obj_names:
src_fs_obj_path = os.path.join(src_top_dir_path, src_fs_obj_name)
if os.path.isfile(src_fs_obj_path) == True:
text_processing(src_fs_obj_path,
src_fs_obj_name,
num_of_headers,
trg_top_dir_path,
rename_ctrl_h_pattern,
rename_ctrl_h_repl)
##Выбор пользователя - производить поиск и
##замену подстрок в файлах, расположенных
##по всему дереву папок верхней папки.
##Пути к файлам к этому моменту могли быть
##уже изменены, да и сами файлы - переименованы.
##Поэтому папочно-файловый объект нужно создавать заново.
##Также важно отметить, что если файлы были ранее переименованы,
##то новые имена будут как в исходной папке, так и в конечной.
elif ctrl_h == 'deep':
for src_parent_dir_path, src_dir_names, src_file_names in os.walk(src_top_dir_path):
#Для сохранения отредактированных файлов нужно
#создать в конечной папке верхнего уровня
#дерево папок, полностью идентичное исходному.
#Чтобы так сделать, нужно найти часть
#каждого пути от верхней исходной папки до
#вложенной исходной папки (относительный путь).
#Для самой верхней исходной папки
#такой путь будет равным пустой строке.
#Создаём конечные папки, расположив их в
#конечной папке верхнего уровня в соответствии
#с полученными относительными путями.
src_parent_dir_rel_path = src_parent_dir_path[len(src_top_dir_path) + 1:]
trg_dir_path = os.path.join(trg_top_dir_path, src_parent_dir_rel_path)
if os.path.exists(trg_dir_path) == False:
os.mkdir(trg_dir_path)
#Перебор названий исходных файлов
#каждого уровня, переименование файлов.
for src_file_name in src_file_names:
src_file_path = os.path.join(src_parent_dir_path, src_file_name)
text_processing(src_file_path,
src_file_name,
num_of_headers,
trg_dir_path,
rename_ctrl_h_pattern,
rename_ctrl_h_repl)