Windows/DOSでは、rename myfile.* yourfile.*
と言って名前を変更できますが、拡張子は保持します。 Linuxではそれはどのように達成されますか?
マニュアルページは拡張子を変更する方法を提案するだけですが、それは私が望むものの反対です。
ボーナス:
実際には、写真の作成日をファイル名に入れて、20091231 2359 New Year.jpg
のようなものを取得したいと思います。それを達成するために、重要なコマンドの組み合わせが必要になるのではないかと心配しています。
これがボーナスの質問に対する答えです。
私は実際に写真の作成日をファイル名に入れて、20091231 2359 NewYear.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
と入力してインストールしてください。)
名前の変更部分については、「名前の変更」プログラムが機能します。これは、manページで見た例と同じですが、切り替えただけです。
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
重要なのは、ファイル名の一部を正規表現で変更する方法を示す例を見た場合、それが必要な唯一の例であるということです。拡張機能は、UNIXファイルシステムでは特別なステータスはありません。これらは、.
文字の後にあるファイル名の一部にすぎません。
ファイル名を操作するさらにいくつかの異なる方法があります
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にはファイル名拡張子はありません。
正規表現を使用して、ファイル名から特定の部分文字列を切り取り、それらにアクセスします。
例:
実際のシナリオ:chmファイルからhtmlを抽出しています。 Windowsのファイル名では大文字と小文字が区別されないため、Linuxではリンクが壊れます。 index.HTMLという名前のファイルがありますが、URLにはhref = "index.html"があります。したがって、あなたの目標は、ファイル名をそれらへのリンクに一致するように適合させることです。
変数にファイル名があると仮定します。
FILENAME='index.HTML'
バージョン3.0以降、bashは正規表現自体をサポートしているため、文字列操作を実行するためにgrep/sed/Perlなどの追加ツールは必要ありません。次の例は、文字列内のバックエンド一致の置換を示しています。
echo ${FILENAME/%\.HTML/.html}
必要に応じて、一致文字列と置換文字列をパラメータ化できます。これにより、スクリプトを作成する際の柔軟性が高まります。次のコードスニペットは同じ目標を達成します。
match='\.HTML'
replacement='.html'
echo ${FILENAME/%$match/$replacement}
追加情報については、bashのドキュメントを参照してください。
それを行うには常に複数の方法があります。次のスクリプトを/ 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";
-X/--keep-extension
オプションはrename
(バージョン1.600)で使用できます。
-X, --keep-extension Save and remove the last extension from a filename, if there is any. The saved extension will be appended back to the filename at the end of the rest of the operations.
rename
は、HomebrewのMacとLinuxbrewのLinuxで利用できます(もちろん、他のインストールオプションもあります)。
ここに別のものがあります:
find -name "*.jpg" -printf '"%p" "%h/%TY%Tm%Td %TH%TM %f"\n' | while read -r f
do
eval "mv ${f}"
done