ファイルがたくさんある場合に備えて、できるだけ効率的に実行したいと思います。
必要なのは、見つけたすべてのファイルの名前を変更し、それらのサフィックスを削除することです。
例:
[/tmp] $ ls -l
a.log
b.log
c.tmp
[/tmp] $ find /tmp -name "*.log" -type f -exec mv {} {%.*} \;
[/tmp] $ ls -l
a
b
c.tmp
これは機能しません。通常のbash変数の場合${var%.*}
var
を返したはずです 最後の.
まで 。
承認された回答:
シェルを開始して、シェルパラメータ拡張演算子を使用します:
find ~/tmp -name '*.log' -type f -exec sh -c '
for file do
mv -i -- "$file" "${file%.*}"
done' sh {} +
/tmp
では実行したくないことに注意してください または、悪意のあるユーザーが任意の.log
の名前を変更できるようにするために、他のユーザーが書き込み可能なディレクトリ ファイルシステム上のファイル¹(またはファイルを任意のディレクトリに移動²)。
いくつかのfind
およびmv
実装では、find -execdir
を使用できます およびmv -T
安全にするために:
find /tmp -name '*.log' -type f -execdir sh -c '
for file do
mv -Ti -- "$file" "${file%.*}"
done' sh {} +
または、rename
を使用します (perlバリアント)rename()
を実行するだけです システムコールなので、ファイルを他のファイルシステムやディレクトリに移動しようとしないでください…
find /tmp -name '*.log' -type f -execdir rename 's/\.log$//' {} +
または、perl
ですべてを実行します :
perl -MFile::Find -le '
find(
sub {
if (/\.log\z/) {
$old = $_;
s/\.log\z//;
rename($old, $_) or warn "rename $old->$_: $!\n"
}
}, @ARGV)' ~/tmp
ただし、perl
に注意してください のFind::File
(GNU find
とは異なります )安全なディレクトリトラバーサル³を実行しないため、/tmp
で実行したいことではありません。 どちらか。
メモ。
¹攻撃者は/tmp/. /auth.log
ファイル、およびfind
の間 それを見つけてmv
それを移動すると(そしてそのウィンドウは簡単に任意に大きくすることができます)、"/tmp/. "
を置き換えます /var/log
へのシンボリックリンクを持つディレクトリ 結果として/var/log/auth.log
名前が/var/log/auth
に変更されます
²さらに悪いことに、攻撃者は/tmp/foo.log
を作成する可能性があります 悪意のあるcrontab
たとえば、/tmp/foo
/etc/cron.d
へのシンボリックリンク そのcrontabをに移動させます /etc/cron.d
。これがmv
のあいまいさです (cp
にも適用されます およびln
少なくとも)それは両方とも移動することができます および移動 。 GNU mv
-t
で修正します (に )および-T
(から )オプション。
³File::Find
chdir("/tmp"); read content; chdir("foo") ...; chdir("bar"); chdir("../..")...
。したがって、誰かが/tmp/foo/bar
を作成できます ディレクトリを適切なタイミングで、名前を/tmp/bar
に変更します。 したがって、chdir("../..")
/
に着陸します 。