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 / .