I'm after a way to batch rename files with a regex i.e.
我正在寻找一种使用regex来批量重命名文件的方法。
s/123/onetwothree/g
I recall i can use awk and sed with a regex but couldnt figure out how to pipe them together for the desired output.
我记得我可以使用awk,并使用regex,但不知道如何将它们连接到所需的输出。
4 个解决方案
#1
19
An efficient way to perform the rename operation is to construct the rename commands in a sed pipeline and feed them into the shell.
执行重命名操作的一种有效方法是在一个sed管道中构造重命名命令并将它们提交到shell中。
ls |
sed -n 's/\(.*\)\(123\)\(.*\)/mv "\1\2\3" "\1onetwothree\2"/p' |
sh
#2
54
You can install perl based rename utility:
您可以安装基于perl的rename实用程序:
brew install rename
and than just use it like:
而不仅仅是像:
rename 's/123/onetwothree/g' *
if you'd like to test your regex without renaming any files just add -n switch
如果您想在不重命名任何文件的情况下测试您的regex,请添加-n开关
#3
4
files = "*"
for f in $files; do
newname=`echo "$f" | sed 's/123/onetwothree/g'`
mv "$f" "$newname"
done
#4
2
My take on a friendly recursive regex file name renamer which by default only emulates the replacement and shows what the resulting file names would be.
我采用了一个友好的递归regex文件名renamer,默认情况下它只模拟替换,并显示结果文件名。
Use -w
to actually write changes when you are satisfied with the dry run result, -s
to suppress displaying non-matching files; -h
or --help
will show usage notes.
当您对运行结果感到满意时,使用-w来实际编写更改,-s来抑制显示不匹配的文件;-h或-help将显示用法说明。
Simplest usage:
最简单的用法:
# replace all occurences of 'foo' with 'bar'
# "foo-foo.txt" >> "bar-bar.txt"
ren.py . 'foo' 'bar' -s
# only replace 'foo' at the beginning of the filename
# "foo-foo.txt" >> "bar-foo.txt"
ren.py . '^foo' 'bar' -s
Matching groups (e.g. \1
, \2
etc) are supported too:
支援配对组(例如\1、\2等):
# rename "spam.txt" to "spam.py"
ren.py . '(.+)\.txt' '\1.py' -s
# rename "12-lovely-spam.txt" to "lovely-spam-12.txt"
# (assuming two digits at the beginning and a 3 character extension
ren.py . '^(\d{2})-(.+)\.(.{3})' '\2-\1.\3' -s
NOTE: don't forget to add
-w
when you tested the results and want to actually write the changes.注意:在测试结果时不要忘记添加-w,并且要实际地编写更改。
Works both with Python 2.x and Python 3.x.
可以同时使用Python 2。x和Python 3. x。
#!/usr/bin/python
# -*- coding: utf-8 -*-
from __future__ import print_function
import argparse
import os
import fnmatch
import sys
import shutil
import re
def rename_files(args):
pattern_old = re.compile(args.search_for)
for path, dirs, files in os.walk(os.path.abspath(args.root_folder)):
for filename in fnmatch.filter(files, "*.*"):
if pattern_old.findall(filename):
new_name = pattern_old.sub(args.replace_with, filename)
filepath_old = os.path.join(path, filename)
filepath_new = os.path.join(path, new_name)
if not new_name:
print('Replacement regex {} returns empty value! Skipping'.format(args.replace_with))
continue
print(new_name)
if args.write_changes:
shutil.move(filepath_old, filepath_new)
else:
if not args.suppress_non_matching:
print('Name [{}] does not match search regex [{}]'.format(filename, args.search_for))
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Recursive file name renaming with regex support')
parser.add_argument('root_folder',
help='Top folder for the replacement operation',
nargs='?',
action='store',
default='.')
parser.add_argument('search_for',
help='string to search for',
action='store')
parser.add_argument('replace_with',
help='string to replace with',
action='store')
parser.add_argument('-w', '--write-changes',
action='store_true',
help='Write changes to files (otherwise just simulate the operation)',
default=False)
parser.add_argument('-s', '--suppress-non-matching',
action='store_true',
help='Hide files that do not match',
default=False)
args = parser.parse_args(sys.argv[1:])
print(args)
rename_files(args)
#1
19
An efficient way to perform the rename operation is to construct the rename commands in a sed pipeline and feed them into the shell.
执行重命名操作的一种有效方法是在一个sed管道中构造重命名命令并将它们提交到shell中。
ls |
sed -n 's/\(.*\)\(123\)\(.*\)/mv "\1\2\3" "\1onetwothree\2"/p' |
sh
#2
54
You can install perl based rename utility:
您可以安装基于perl的rename实用程序:
brew install rename
and than just use it like:
而不仅仅是像:
rename 's/123/onetwothree/g' *
if you'd like to test your regex without renaming any files just add -n switch
如果您想在不重命名任何文件的情况下测试您的regex,请添加-n开关
#3
4
files = "*"
for f in $files; do
newname=`echo "$f" | sed 's/123/onetwothree/g'`
mv "$f" "$newname"
done
#4
2
My take on a friendly recursive regex file name renamer which by default only emulates the replacement and shows what the resulting file names would be.
我采用了一个友好的递归regex文件名renamer,默认情况下它只模拟替换,并显示结果文件名。
Use -w
to actually write changes when you are satisfied with the dry run result, -s
to suppress displaying non-matching files; -h
or --help
will show usage notes.
当您对运行结果感到满意时,使用-w来实际编写更改,-s来抑制显示不匹配的文件;-h或-help将显示用法说明。
Simplest usage:
最简单的用法:
# replace all occurences of 'foo' with 'bar'
# "foo-foo.txt" >> "bar-bar.txt"
ren.py . 'foo' 'bar' -s
# only replace 'foo' at the beginning of the filename
# "foo-foo.txt" >> "bar-foo.txt"
ren.py . '^foo' 'bar' -s
Matching groups (e.g. \1
, \2
etc) are supported too:
支援配对组(例如\1、\2等):
# rename "spam.txt" to "spam.py"
ren.py . '(.+)\.txt' '\1.py' -s
# rename "12-lovely-spam.txt" to "lovely-spam-12.txt"
# (assuming two digits at the beginning and a 3 character extension
ren.py . '^(\d{2})-(.+)\.(.{3})' '\2-\1.\3' -s
NOTE: don't forget to add
-w
when you tested the results and want to actually write the changes.注意:在测试结果时不要忘记添加-w,并且要实际地编写更改。
Works both with Python 2.x and Python 3.x.
可以同时使用Python 2。x和Python 3. x。
#!/usr/bin/python
# -*- coding: utf-8 -*-
from __future__ import print_function
import argparse
import os
import fnmatch
import sys
import shutil
import re
def rename_files(args):
pattern_old = re.compile(args.search_for)
for path, dirs, files in os.walk(os.path.abspath(args.root_folder)):
for filename in fnmatch.filter(files, "*.*"):
if pattern_old.findall(filename):
new_name = pattern_old.sub(args.replace_with, filename)
filepath_old = os.path.join(path, filename)
filepath_new = os.path.join(path, new_name)
if not new_name:
print('Replacement regex {} returns empty value! Skipping'.format(args.replace_with))
continue
print(new_name)
if args.write_changes:
shutil.move(filepath_old, filepath_new)
else:
if not args.suppress_non_matching:
print('Name [{}] does not match search regex [{}]'.format(filename, args.search_for))
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Recursive file name renaming with regex support')
parser.add_argument('root_folder',
help='Top folder for the replacement operation',
nargs='?',
action='store',
default='.')
parser.add_argument('search_for',
help='string to search for',
action='store')
parser.add_argument('replace_with',
help='string to replace with',
action='store')
parser.add_argument('-w', '--write-changes',
action='store_true',
help='Write changes to files (otherwise just simulate the operation)',
default=False)
parser.add_argument('-s', '--suppress-non-matching',
action='store_true',
help='Hide files that do not match',
default=False)
args = parser.parse_args(sys.argv[1:])
print(args)
rename_files(args)