Форум сайта python.su
7
Делаю подобие стандартной линуксовой rename, но эта стандартная не работает с регекспами.
Но есть проблемы, а точнее не переименовывает в некоторых случаях, при этом при обычном принте - всё хорошо.
Итак, код скрипта:
import re import os import sys import subprocess def main(cwd, pattern, rename_pattern): for filename in os.listdir(cwd): new_filename = re.sub(pattern, rename_pattern, filename) subprocess.call('mv %s %s' % (filename, new_filename), shell=True) if __name__ == '__main__': cwd = os.getcwd() pattern = sys.argv[1] rename_pattern = sys.argv[2] main(cwd, pattern, rename_pattern)
Офлайн
253
Зачем mv? Не будет работать под windows. shutil.move, os.rename?
Переименовка по регэкспу: А чем вам find не угодил?
Master_SergiusВ консоли чтоли?
проставить руками экранирование
Отредактировано doza_and (Янв. 3, 2014 22:26:59)
Офлайн
7
Я имел это ввиду:
import re import os import sys import subprocess ESCAPING_LIST = [' ', '(', ')'] def escape_symbols(string): for item in ESCAPING_LIST: string = string.replace(item, '\%s' % item) return string def main(cwd, pattern, rename_pattern): for filename in os.listdir(cwd): new_filename = re.sub(pattern, rename_pattern, filename) filename = escape_symbols(filename) new_filename = escape_symbols(new_filename) #print filename, ' ',new_filename subprocess.call(r'mv %s %s' % (filename, new_filename), shell=True) if __name__ == '__main__': cwd = os.getcwd() pattern = sys.argv[1] rename_pattern = sys.argv[2] main(cwd, pattern, rename_pattern)
Отредактировано Master_Sergius (Янв. 3, 2014 22:15:50)
Офлайн
253
получилось и ладненько. Есть еще
re.escape(string)
Отредактировано doza_and (Янв. 3, 2014 22:33:03)
Офлайн
7
Может быть сообразите идеальный вариант такого ренайма в целом? Да так, чтобы и линку в пользовательский каталог запихнуть? буду премного благодарен ))
Офлайн
7
Вот, пока что такой окончательный вариант, для работы в той же папке
import re import os import sys def main(cwd, pattern, rename_pattern): for filename in os.listdir(cwd): new_filename = re.sub(pattern, rename_pattern, filename) filename = escape_symbols(filename) new_filename = escape_symbols(new_filename) if filename != new_filename: os.rename(filename, new_filename) if __name__ == '__main__': cwd = os.getcwd() pattern = sys.argv[1] rename_pattern = sys.argv[2] main(cwd, pattern, rename_pattern)
Отредактировано Master_Sergius (Янв. 4, 2014 10:04:43)
Офлайн
857
Master_Sergiusrename на перле есть, ищи по Larry Wall
1) может есть всё таки способ переименования группы файлов по регекспу?
Master_Sergiusне, надо просто использовать список для вызова
при запуске же получаю естественно ошибки, так как надо бы екранировать пробелы, скобки и т.п. для mv команды…
Master_Sergiusтам просто не хватает одинарных кавычек вокруг каждого аргумента
2) как можно легко и безошибочно проставить руками экранирование нужных символов?
Офлайн
253
ну хорошую утилиту трудно сделать. Что вы хотите от символьных ссылок мне непонятно.
#! /bin/env/python # -*- coding:utf-8 -*- u""" As unix rename but regular expression syntax""" import argparse import shutil,os import re # парадигма - разработка через тестирование def mk_fil(data): with open("a.dat","w") as f: f.write(str(data)) return "a.dat" def make_test_dir(): os.renames(mk_fil(1),"aaa/a1.dat") os.renames(mk_fil(2),"aaa/a2.dat") os.renames(mk_fil(3),"aaa/bbb/a3.dat") os.renames(mk_fil(3),"aaa/bbb/a4.dat") os.renames(mk_fil(3),"aaa/bbb/4a.dat") def test_rrename_nr(): make_test_dir() try: rrename(ur"([a-z]+)(\d+)",ur"\2\1","aaa") assert(os.path.exists("aaa/1a.dat") and os.path.exists("aaa/2a.dat") and os.path.exists("aaa/bbb/a3.dat") and os.path.exists("aaa/bbb/a4.dat") ) finally: shutil.rmtree("aaa") def test_rrename_r(): make_test_dir() try: rrename(ur"([a-z]+)(\d+)",ur"\2\1","aaa",recursive=1) assert(os.path.exists("aaa/1a.dat") and os.path.exists("aaa/2a.dat") and os.path.exists("aaa/bbb/3a.dat") and os.path.exists("aaa/bbb/4a.dat") and os.path.exists("aaa/bbb/a4.dat") ) finally: shutil.rmtree("aaa") def test_rrename_rf(): make_test_dir() try: rrename(ur"([a-z]+)(\d+)",ur"\2\1","aaa",recursive=1,force=1) assert(os.path.exists("aaa/1a.dat") and os.path.exists("aaa/2a.dat") and os.path.exists("aaa/bbb/3a.dat") and os.path.exists("aaa/bbb/4a.dat") and not os.path.exists("aaa/bbb/a4.dat") ) finally: shutil.rmtree("aaa") # символьные ссылки лениво тестировать # собственно код def file_iter(root,recursive=False,symlinks=False): if recursive: for di, dl, fl in os.walk(root,followlinks=symlinks): for f in fl: yield os.path.join(di, f) else: di, dl, fl = os.walk(root).next() for f in fl: yield os.path.join(di, f) # интерфейс для программного использования def rrename(src,target,root=".", force=False, recursive=False, symlinks=False): ex = re.compile(src) ifail = 0 for oldname in file_iter(root,recursive,symlinks): newname, n = ex.subn(target,oldname) if n: if force and os.path.exists(newname): os.remove(newname) try: os.rename(oldname,newname) except OSError: ifail+=1 print "fail rename {0} -> {1}".format(oldname,newname) return ifail # интерфейс для консоли if __name__ == '__main__': parser = argparse.ArgumentParser(prog="rrename",description="rename files by regular expression replace") parser.add_argument("-r","--recursive",action='store_true',help=u"search files in subdirs") parser.add_argument("-f","--force",action='store_true',help=u"force file overwrite") parser.add_argument("-s","--symlinks",action='store_true',help=u"follow symlinks") parser.add_argument("-d","--directory",help=u"root directory") parser.add_argument("patterns",nargs="2",help=u"input_pattern output_pattern") args = parser.parse_args() root = args.directory if not root: root = "." sys.exit(rrename(args.patterns[0],args.patterns[1],root,args.force,args.recursive,args.symlinks))
Отредактировано doza_and (Янв. 4, 2014 11:11:38)
Офлайн
7
Ох, нифига ж себе код получился! Ясно, там сразу с тестами, но ух, как страшно )
Что Я хотел от ссылок - это чтобы можно было мой скрипт запустить как обычную линуксовую утилиту, не указывая путь к запускаемому файлу, и чтобы правильно текущую директорию разбирал… Теоретически, Я догадываюсь как это сделать - линку запихнуть в один из bin каталогов, прописаных в переменной окружения PATH, а каталог передать наверное, как переменную окружения PWD.
И куда вообще желательно поместить мой скрипт?
Офлайн
253
Master_SergiusПо уму вы должны открыть для себя setup.py http://pythonhosted.org/setuptools/setuptools.html. Пишете setup скрипт, он все правильно добавит. Логика такая - есть место где вы все разрабатываете, потом запускаете setup.py и оно копируется в нужное место вашей системы. Но вообще достаточно поместить в любое место (например /usr/bin,opt и т.п.) доступное в путях, корректно прописать первую строку и задать права на выполнение. Не спец в unix почитайте например http://proubuntu.com.ua/2011/10/27/dir.html.
И куда вообще желательно поместить мой скрипт?
Master_SergiusТам кода 3 абзаца. И то третий потому что захотелось рекурсивное переименовывание сделать. Тест надо вынести в отдельный файл. Мне было лень границы ставить и использовать unittest поэтому я под nosetests заточил. Если оно вам надо могу кнуть окончательный вариант из 2 файлов (по уму должны еще быть setup.py и документация)
нифига ж себе код получился!
Офлайн