В Windows/DOS я могу сказать rename myfile.* yourfile.*
изменить имя, но сохранить расширение. Как это выполняется на Linux?
Страница справочника только предлагает, как изменить расширение, но это - противоположность того, что я хочу.
Премия:
Я на самом деле хочу поместить дату создания фотографии в ее имя файла, получить что-то как 20091231 2359 New Year.jpg
. Я боюсь, что мне нужна некоторая нетривиальная комбинация команд для достижения этого?
Вот ответ для вопроса о премии.
Я на самом деле хочу поместить дату создания фотографии в ее имя файла, получить что-то как 20091231 2 359 Новых Year.jpg. Я боюсь, что мне нужна некоторая нетривиальная комбинация команд для достижения этого?
Принятие Вас хочет взять дату создания фотографии от данных EXIF, Вам будет нужен отдельный инструмент для этого. К счастью это оказывается этим jhead
предлагает тривиальный способ сделать точно, что Вы хотите с -n
опция.
$ jhead -h
[...]
-n[format-string]
Rename files according to date. Uses exif date if present, file
date otherwise. If the optional format-string is not supplied,
the format is mmdd-hhmmss. If a format-string is given, it is
is passed to the 'strftime' function for formatting
In addition to strftime format codes:
'%f' as part of the string will include the original file name
[...]
Вот пример:
$ jhead -n%Y-%m-%d-%f New_year.jpg
New_year.jpg --> 2009-12-31-New_year.jpg
Править: Конечно, чтобы сделать это для набора фотографий, это было бы что-то как:
$ for i in *jpg; do jhead -n%Y-%m-%d-%f $i; done
Для тонкой настройки форматирования даты к симпатии смотрите на вывод date --help
, например; это перечислит коды доступного формата.
(jhead широко доступно для различных систем. Если Вы, например, на Ubuntu или Debian, просто введите sudo apt-get install jhead
устанавливать его.)
Для просто части переименования будет работать 'переименовать' программа. Это совпадает с примером, который Вы видели в странице справочника, просто передвинутой.
justin@eee:/tmp/q$ touch myfile.{a,b,c,d}
justin@eee:/tmp/q$ ls
myfile.a myfile.b myfile.c myfile.d
justin@eee:/tmp/q$ rename -v s/myfile/yourfile/ myfile.*
myfile.a renamed as yourfile.a
myfile.b renamed as yourfile.b
myfile.c renamed as yourfile.c
myfile.d renamed as yourfile.d
justin@eee:/tmp/q$ ls
yourfile.a yourfile.b yourfile.c yourfile.d
justin@eee:/tmp/q$
betelgeuse:tmp james$ ls myfile.* yourfile.*
ls: yourfile.*: No such file or directory
myfile.a myfile.b
betelgeuse:tmp james$ for file
> in myfile.*
> do
> mv "${file}" "`echo $file | sed 's/myfile\./yourfile./'`"
> done
betelgeuse:tmp james$ ls myfile.* yourfile.*
ls: myfile.*: No such file or directory
yourfile.a yourfile.b
Ключ - то, что, если Вы видели пример, который показывает, как к munge одна часть имени файла с regex, это - единственный пример, в котором Вы нуждаетесь. Расширения не имеют никакого особого статуса в файловых системах Unix - они - просто часть имени файла, которое, оказывается, после a .
символ.
Вот пара более различных способов управлять именами файлов
for f in *.jpg
do
mv "$f" "before_part${f%.*}after_part.${f##*.}"
# OR mv "$f" "before_part$(basename "$f" ".jpg")after_part.jpg"
done
Расширения параметра в mv
управляйте работой следующим образом:
${f%.*}
- Удалите самый короткий шаблон соответствия из конца строки, содержавшейся в $f
, в этом случае удалите все после и включая последнюю точку. Сингл %
означает "самый короткий от конца".
${f##*.}
- Удалите самый длинный шаблон соответствия с начала строки, содержавшейся в $f
, в этом случае все прежде и включая последнюю точку (это включает любые другие точки также). Двойное #
(##
) означает "самый длинный с начала".
Так, например, если $f
содержит "Foo.bar.baZ.jpg":
echo "${f%.*}"
дает
Foo.bar.baZ
и
echo "${f##*.}"
дает
jpg
Так mv
команда, когда-то расширенная, была бы похожа:
mv "Foo.bar.baZ.jpg" "before_partFoo.bar.baZafter_part.jpg"
В Linux нет никаких расширений файла.
Используйте регулярные выражения, чтобы сократить конкретные подстроки из имени файла и получить доступ к ним.
Пример:
Реальный сценарий: Вы извлекаете HTML из файла председателя. Имена файлов в Windows нечувствительны к регистру, таким образом, в Linux Вы получите неработающие ссылки. У Вас есть файл под названием index.HTML, но href = "index.html" в URL. Таким образом, Ваша цель состоит в том, чтобы адаптировать имена файлов для соответствия ссылкам на них.
Предположите, что у Вас есть имя файла в переменной:
FILENAME='index.HTML'
Запуск с удара версии 3.0 поддерживает регулярные выражения самого, таким образом, Вам не нужны никакие дополнительные инструменты как grep/sed/perl и т.д. для выполнения обработки строк. Следующий пример иллюстрирует замену соответствия бэкенда в строке:
echo ${FILENAME/%\.HTML/.html}
Строки совпадения и замещающие строки могут быть параметризованы, при необходимости это обеспечивает дополнительную гибкость при записи сценария. Следующий фрагмент кода достигает той же цели:
match='\.HTML'
replacement='.html'
echo ${FILENAME/%$match/$replacement}
Консультируйтесь с документами удара для получения дополнительной информации.
Вот другой:
find -name "*.jpg" -printf '"%p" "%h/%TY%Tm%Td %TH%TM %f"\n' | while read -r f
do
eval "mv ${f}"
done
Всегда существует больше чем один способ сделать это. Я поместил следующий сценарий как/usr/local/bin/mrename.
Затем в сценарии, содержащем фото файлы, просто введите: mrename
Существует также дополнительная прокомментированная функция в сценарии для масштабирования фотографий (использующий ImageMagick).
Надежда это полезно для некоторых людей.
#!/usr/bin/perl
#
# mrename files
#
#
use strict;
# if no 2 args, use defaults
my $dir = ".";
# read in path from command line
$dir = $ARGV[0] if ( defined( $ARGV[0] ) && $ARGV[0] ne "" );
# read in directory contents
opendir( DIR, $dir );
my @files = readdir( DIR );
closedir( DIR );
# rename and/or scale each file in directory
my $number_of_files = scalar( @files );
my $curfile = 0;
foreach my $file( @files ) {
# only rename and scale jpg/gif files
if ( $file =~ /\w+\.(jpg)$/ ) {
my $extension = $1;
$extension =~ tr/A-Z/a-z/;
my $full_filename = "$dir/$file";
# get stats on file- specifically the last modified time
(my $dev,my $ino,my $mode,my $nlink,my $uid,my $gid,my $rdev,my $size,
my $atime,my $mtime,my $ctime,my $blksize,my $blocks) = stat($full_filename);
# convert last-modified time from seconds to practical datetime terms
(my $sec,my $min,my $hour,my $mday,my $mon,my $year,my $wday,my $yday,
my $isdst) = localtime($mtime);
++$mon;
$year += 1900;
my $filecdate = sprintf( "m%04i%02i%02i_%02i%02i%02i.$extension", $year, $mon, $mday, $hour, $min, $sec );
my $full_newfilename = "$dir/$filecdate";
# to scale files, use imagemagick by using the command below instead of mv
#my $cmd = "convert $full_filename -resize $scale% $full_newfilename";
my $cmd = "mv $full_filename $full_newfilename";
system( $cmd );
# update percentage done
my $percent_done = sprintf( "%5.2lf", 100* (++$curfile) / $number_of_files );
print "\r$percent_done%";
}
}
print "\n";