web-dev-qa-db-ja.com

OS Xターミナルでファイルの名前を一括変更する正規表現

私は正規表現でファイルの名前を一括変更する方法を求めています.

s/123/onetwothree/g

私はawkを使用して正規表現でsedできるが、それらを一緒にパイプして目的の出力を得る方法を理解できなかったことを思い出します。

31
user370507

名前変更操作を実行する効率的な方法は、sedパイプラインで名前変更コマンドを作成し、それらをシェルにフィードすることです。

ls |
sed -n 's/\(.*\)\(123\)\(.*\)/mv "\1\2\3" "\1onetwothree\2"/p' |
sh
19

Perlベースの名前変更ユーティリティをインストールできます。

brew install rename

次のように使用するだけです:

rename 's/123/onetwothree/g' *

ファイルの名前を変更せずに正規表現をテストする場合は、-nスイッチを追加するだけです

73
Viperet
files = "*"
for f in $files; do
     newname=`echo "$f" | sed 's/123/onetwothree/g'`
     mv "$f" "$newname"
done
5
Fred Foo

私はフレンドリーで再帰的なregexファイル名リネーム機能を採用しています。これはデフォルトでは置換のみをエミュレートし、結果のファイル名がどうなるかを示します。

-wを使用して、ドライランの結果に満足したときに実際に変更を書き込みます。-sを使用して、一致しないファイルの表示を抑制します。 -hまたは--helpは、使用上の注意を表示します。

最も簡単な使い方:

# 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

一致するグループ(\1\2など)もサポートされています。

# rename "spam.txt" to "spam-spam-spam.py"
ren.py . '(.+)\.txt' '\1-\1-\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

注:結果をテストして実際に変更を書き込みたい場合は、-wを追加することを忘れないでください。

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)
4
ccpizza

ネームチェンジャーは超ニースです。検索と置換の正規表現をサポートしています。次の正規表現を使用して、非常に複雑な名前変更を行っていることを考慮してください:\.sync-conflict-.*\.それは命の恩人です。

enter image description here

3
Tomachi