0

我正在寻找一种方法来根据下面提到的标准对一堆文件进行批量重命名:

文件列表看起来与此类似,并且应该是字母数字:

  • A20100102-1.loc.txt
  • A20100102.loc.txt
  • A20100103-1.loc.txt
  • A20100103.loc.txt ...等。

以下伪代码非常接近我希望它的行为方式,但我试图弄清楚 sed、awk、python、perl 或 bash 脚本是否是要走的路(我正在检查选项为了弄清楚我可能想要更深入地研究哪种实现):

for all_files_in_dir:{
  if(currentfile.name is_close_to previousfile.name){  //maybe regex here
    var small_file = find_smaller_file_filename(currentfile.filesize, previousfile.filesize);
    sys.remove(small_file);
  }
}

感谢您的任何建议!

4

3 回答 3

2
import os
import re

def rm_smaller_of(regex, dir):
    for entry in os.listdir(dir):
        if re.match(regex, entry[:9]):
            matches = [(os.stat(f).st_size, f) for f in os.listdir(dir) 
                        if f[:9] == entry[:9]]
            matches.sort(reverse=True)
            for d in matches[1:]:
                os.remove(d[1])

我认为这应该有效。

>>> rm_smaller_of('[A-Z]\d{8}$', '/home/you/list')
于 2012-11-05T19:26:00.053 回答
1

我的条目:不是那么简洁,但希望可读。

import sys, os
from collections import defaultdict

filenames = sys.argv[1:]

# collect like-named files
groups = defaultdict(set)
for filename in filenames:
    key = filename.split('.')[0].split("-")[0]
    groups[key].add(filename)

# work on each group
for names in groups.values():
    target_name = sorted(names)[0] # or min(names, key=len), or whatever
    largest_file = max(names, key=os.path.getsize)

    os.rename(largest_file, target_name)

    to_remove = names.difference((largest_file, target_name))
    for name in to_remove:
        os.remove(name)
于 2012-11-05T19:52:23.563 回答
1

我将在 Perl 中发布一个解决方案,只是因为您不认为这是一种可能性:)

$currentPrefix = "";
$previousFile = "";
while (<*.txt>) {
  /([A-Z]+[0-9]+)-?[0-9]*.loc.txt/;
  if ($1 eq $currentPrefix) {
    if (-s $_ < -s $previousFile) {
      unlink($_);
    } else {
      unlink($previousFile);
      $previousFile = $_;
    }
  } else {
    $currentPrefix = $1;
    $previousFile = $_;
  }
}

python中的另一个解决方案:

import glob
import os
import re

currentPrefix = ""
previousFile = ""
for filename in sorted(glob.glob('*.txt')):
  match = re.match(r'([A-Z]+[0-9]+)-?[0-9]*.loc.txt', filename)
  if match and match.group(1) == currentPrefix:
    if os.stat(filename).st_size < os.stat(previousFile).st_size:
      os.remove(filename)
    else:
      os.remove(previousFile)
      previousFile = filename
  else:
    currentPrefix = match.group(1)
    previousFile = filename

请注意,您需要对文件进行排序,因为 glob 不会按字典顺序返回它们……</p>

于 2012-11-05T19:07:39.523 回答