Saya ingin melakukannya seefisien mungkin jika ada banyak file.
Yang saya inginkan adalah mengganti nama semua file yang saya temukan dan menghapus akhirannya.
Misalnya:
[/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
Ini tidak berfungsi. Jika itu adalah variabel bash normal ${var%.*}
akan mengembalikan var
sampai .
.
Jawaban yang Diterima:
Mulai shell untuk menggunakan operator ekspansi parameter shell:
find ~/tmp -name '*.log' -type f -exec sh -c '
for file do
mv -i -- "$file" "${file%.*}"
done' sh {} +
Perhatikan bahwa Anda tidak ingin melakukannya di /tmp
atau direktori apa pun yang dapat ditulis oleh orang lain karena itu akan memungkinkan pengguna jahat membuat Anda mengganti nama .log
sewenang-wenang file di sistem file¹ (atau pindahkan file ke direktori mana pun²).
Dengan beberapa find
dan mv
implementasi, Anda dapat menggunakan find -execdir
dan mv -T
agar lebih aman:
find /tmp -name '*.log' -type f -execdir sh -c '
for file do
mv -Ti -- "$file" "${file%.*}"
done' sh {} +
Atau gunakan rename
(varian Perl) yang hanya akan melakukan rename()
panggilan sistem jadi jangan mencoba memindahkan file ke sistem file lain atau ke direktori…
find /tmp -name '*.log' -type f -execdir rename 's/\.log$//' {} +
Atau lakukan semuanya dalam perl
:
perl -MFile::Find -le '
find(
sub {
if (/\.log\z/) {
$old = $_;
s/\.log\z//;
rename($old, $_) or warn "rename $old->$_: $!\n"
}
}, @ARGV)' ~/tmp
Tetapi perhatikan bahwa perl
Find::File
(bertentangan dengan GNU find
) tidak melakukan traversal direktori yang aman³, jadi itu bukan sesuatu yang ingin Anda lakukan di /tmp
baik.
Catatan.
penyerang dapat membuat /tmp/. /auth.log
file, dan di antara find
menemukannya dan mv
memindahkannya (dan jendela itu dapat dengan mudah dibuat besar sewenang-wenang) ganti "/tmp/. "
direktori dengan symlink ke /var/log
menghasilkan /var/log/auth.log
diganti namanya menjadi /var/log/auth
² Jauh lebih buruk, penyerang dapat membuat /tmp/foo.log
crontab
yang berbahaya misalnya dan /tmp/foo
symlink ke /etc/cron.d
dan membuat Anda memindahkan crontab itu ke /etc/cron.d
. Itulah ambiguitas dengan mv
(juga berlaku untuk cp
dan ln
setidaknya) yang bisa keduanya pindah ke dan pindah ke . GNU mv
memperbaikinya dengan -t
(ke ) dan -T
(ke ) pilihan.
File::Find
melintasi direktori dengan melakukan chdir("/tmp"); read content; chdir("foo") ...; chdir("bar"); chdir("../..")...
. Jadi seseorang dapat membuat /tmp/foo/bar
direktori dan pada saat yang tepat, ganti namanya menjadi /tmp/bar
jadi chdir("../..")
akan mendaratkan Anda di /
.