Пакетное переименование последовательных файлов путем заполнения нулями
У меня есть куча файлов, названных так:
output_1.png
output_2.png
...
output_10.png
...
output_120.png
Какой самый простой способ переименовать их в соответствии с соглашением, например, с максимум четырьмя десятичными знаками, чтобы файлы назывались:
output_0001.png
output_0002.png
...
output_0010.png
output_0120.png
Это должно быть легко в Unix/Linux/BSD, хотя у меня также есть доступ к Windows. Любой язык - это хорошо, но меня интересуют некоторые действительно аккуратные строки (если они есть?).
10 ответов
питон
import os
path = '/path/to/files/'
for filename in os.listdir(path):
prefix, num = filename[:-4].split('_')
num = num.zfill(4)
new_filename = prefix + "_" + num + ".png"
os.rename(os.path.join(path, filename), os.path.join(path, new_filename))
Вы можете составить список допустимых имен файлов, предполагая, что все файлы, которые начинаются с "output_" и заканчиваются на ".png", являются действительными файлами:
l = [(x, "output" + x[7:-4].zfill(4) + ".png") for x in os.listdir(path) if x.startswith("output_") and x.endswith(".png")]
for oldname, newname in l:
os.rename(os.path.join(path,oldname), os.path.join(path,newname))
удар
(от: http://www.walkingrandomly.com/?p=2850)
Другими словами, я заменяю file1.png на file001.png, а file20.png на file020.png и так далее. Вот как это сделать в Bash
#!/bin/bash
num=`expr match "$1" '[^0-9]*\([0-9]\+\).*'`
paddednum=`printf "%03d" $num`
echo ${1/$num/$paddednum}
Сохраните вышеупомянутое в файл с именем zeropad.sh
а затем выполните следующую команду, чтобы сделать его исполняемым
chmod +x ./zeropad.sh
Затем вы можете использовать zeropad.sh
Сценарий следующим образом
./zeropad.sh frame1.png
который вернет результат
frame001.png
Осталось только использовать этот скрипт для переименования всех файлов.png в текущем каталоге, чтобы они были добавлены в ноль.
for i in *.png;do mv $i `./zeropad.sh $i`; done
Perl
(из: Zero pad rename например Image (2).jpg -> Image (002).jpg)
use strict;
use warnings;
use File::Find;
sub pad_left {
my $num = shift;
if ($num < 10) {
$num = "00$num";
}
elsif ($num < 100) {
$num = "0$num";
}
return $num;
}
sub new_name {
if (/\.jpg$/) {
my $name = $File::Find::name;
my $new_name;
($new_name = $name) =~ s/^(.+\/[\w ]+\()(\d+)\)/$1 . &pad_left($2) .')'/e;
rename($name, $new_name);
print "$name --> $new_name\n";
}
}
chomp(my $localdir = `pwd`);# invoke the script in the parent-directory of the
# image-containing sub-directories
find(\&new_name, $localdir);
переименовывать
Также сверху ответьте:
rename 's/\d+/sprintf("%04d",$&)/e' *.png
Довольно легко, хотя он сочетает в себе несколько функций, которые не сразу очевидны:
@echo off
setlocal enableextensions enabledelayedexpansion
rem iterate over all PNG files:
for %%f in (*.png) do (
rem store file name without extension
set FileName=%%~nf
rem strip the "output_"
set FileName=!FileName:output_=!
rem Add leading zeroes:
set FileName=000!FileName!
rem Trim to only four digits, from the end
set FileName=!FileName:~-4!
rem Add "output_" and extension again
set FileName=output_!FileName!%%~xf
rem Rename the file
rename "%%f" "!FileName!"
)
Изменить: неправильно прочитал, что вы не после пакетного файла, но любое решение на любом языке. Простите за это. Чтобы восполнить это, PowerShell с одним вкладышем:
gci *.png|%{rni $_ ('output_{0:0000}.png' -f +($_.basename-split'_')[1])}
Придерживайтесь ?{$_.basename-match'_\d+'}
там, если у вас есть другие файлы, которые не следуют этому шаблону.
На самом деле мне просто нужно было сделать это на OSX. Вот сценарии, которые я создал для него - одна строка!
> for i in output_*.png;do mv $i `printf output_%04d.png $(echo $i | sed 's/[^0-9]*//g')`; done
Для массового переименования единственным безопасным решением является mmv
- проверяет наличие коллизий и позволяет переименовывать в цепочки и циклы, что выходит за рамки большинства сценариев. К сожалению, нулевое заполнение не слишком жарко. Аромат:
c:> mmv output_[0-9].png output_000#1.png
Вот один из обходных путей:
c:> type file
mmv
[^0-9][0-9] #1\00#2
[^0-9][0-9][^0-9] #1\00#2#3
[^0-9][0-9][0-9] #1\0#2#3
[^0-9][0-9][0-9][^0-9] #1\0#2#3
c:> mmv <file
Вот скрипт Python, который я написал, который дополняет нулями в зависимости от наибольшего числа и игнорирует ненумерованные файлы в данном каталоге. Использование:
python ensure_zero_padding_in_numbering_of_files.py /path/to/directory
Тело сценария:
import argparse
import os
import re
import sys
def main(cmdline):
parser = argparse.ArgumentParser(
description='Ensure zero padding in numbering of files.')
parser.add_argument('path', type=str,
help='path to the directory containing the files')
args = parser.parse_args()
path = args.path
numbered = re.compile(r'(.*?)(\d+)\.(.*)')
numbered_fnames = [fname for fname in os.listdir(path)
if numbered.search(fname)]
max_digits = max(len(numbered.search(fname).group(2))
for fname in numbered_fnames)
for fname in numbered_fnames:
_, prefix, num, ext, _ = numbered.split(fname, maxsplit=1)
num = num.zfill(max_digits)
new_fname = "{}{}.{}".format(prefix, num, ext)
if fname != new_fname:
os.rename(os.path.join(path, fname), os.path.join(path, new_fname))
print "Renamed {} to {}".format(fname, new_fname)
else:
print "{} seems fine".format(fname)
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))
$rename output_ output_0 output_? # adding 1 zero to names ended in 1 digit
$rename output_ output_0 output_?? # adding 1 zero to names ended in 2 digits
$rename output_ output_0 output_??? # adding 1 zero to names ended in 3 digits
Это оно!
с разделением bash,
linux
for f in *.png;do n=${f#*_};n=${n%.*};mv $f $(printf output_"%04d".png $n);done
окна (bash)
for f in *.png;do n=${f#*_};mv $f $(printf output_"%08s" $n);done
С помощью
ls + awk + sh
:
ls -1 | awk -F_ '{printf "%s%04d.png\n", "mv "$0" "$1"_", $2}' | sh
Если вы хотите протестировать команду перед ее запуском, просто удалите
| sh
Я следую из решения Адама для OSX.
Некоторые ошибки, с которыми я столкнулся в моем сценарии:
- У меня был набор файлов.mp3, поэтому sed перехватывал " 3 " в суффиксе " .mp3 ". (Я использовал basename вместо echo, чтобы исправить это)
- У моих.mp3 были пробелы в их именах, например, " звуковая дорожка 1.mp3 ", это приводило к тому, что basename + sed немного испортились, поэтому мне пришлось заключить в кавычки параметр "$i".
В итоге моя конверсионная строка выглядела так:
for i in *.mp3 ; do mv "$i" `printf "track_%02d.mp3\n" $(basename "$i" .mp3 | sed 's/[^0-9]*//g')` ; done
Я просто хочу снять замедленный фильм, используя
ffmpeg -pattern_type glob -i "*.jpg" -s:v 1920x1080 -c:v libx264 output.mp4
и возникла аналогичная проблема.
[image2 @ 000000000039c300] Был выбран тип шаблона 'glob', но эта сборка libavformat не поддерживает подстановку
glob не поддерживается в Windows 7. Также, если в списке файлов, как показано ниже, используется%2d.jpg или%02d.jpg
1.jpg2.jpg ... 10.jpg11.jpg...
[image2 @ 00000000005ea9c0] Could find no file with path '%2d.jpg' and index in the range 0-4
%2d.jpg: No such file or directory
[image2 @ 00000000005aa980] Could find no file with path '%02d.jpg' and index in the range 0-4
%02d.jpg: No such file or directory
вот мой пакетный скрипт для переименования мух
@echo off
setlocal enabledelayedexpansion
set i=1000000
set X=1
for %%a in (*.jpg) do (
set /a i+=1
set "filename=!i:~%X%!"
echo ren "%%a" "!filename!%%~xa"
ren "%%a" "!filename!%%~xa"
)
после переименования 143 323 файлов jpg,
ffmpeg -i %6d.jpg -s:v 1920x1080 -c:v libx264 output.mp4