ファイル数が多い場合は、できるだけ効率的にこれを行いたいと思います。私が望むのは、私が見つけたすべてのファイルの名前を変更し、対応するサフィックスを削除することです。
たとえば、
[/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
.
ベストアンサー1
シェル・パラメーター拡張演算子を使用するには、シェルを開始します。
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
s Find::File
(GNUとは対照的にfind
)は安全なディレクトリナビゲーションを実行しないため、これを行うこともできません/tmp
。
メモ。
¹攻撃者は/tmp/. /auth.log
ファイルを作成し、ファイルのfind
検索と移動の間のシンボリックリンクでディレクトリを置き換えることができますmv
(ウィンドウは任意に大きくなる可能性があります)。"/tmp/. "
/var/log
/var/log/auth.log
/var/log/auth
²さらに悪いことに、攻撃者がcrontabを移動する可能性のある/tmp/foo.log
マルウェアcrontab
と/tmp/foo
シンボリックリンクを生成できる可能性があります。/etc/cron.d
入力する /etc/cron.d
。これはmv
(少なくとも適用されてcp
)ln
あいまいさがあるかもしれません。移動するそして引っ越す。 GNUmv
は-t
(入力する)と-T
(到着)オプション。
File::Find
³を実行してディレクトリをトラバースしますchdir("/tmp"); read content; chdir("foo") ...; chdir("bar"); chdir("../..")...
。したがって、誰かがディレクトリを作成し、適切な/tmp/foo/bar
ときに名前を変更してください。/tmp/bar
chdir("../..")
/