GNU/Linux >> Belajar Linux >  >> Linux

Memanipulasi {} Mengembalikan String Dari Find -exec?

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.

Terkait:Gunakan Tanggal Variabel dalam Perintah Sed?

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


Linux
  1. Temukan Geolokasi Alamat IP Dari Commandline

  2. Tes Shell Untuk Menemukan Pola Dalam String?

  3. Temukan -exec + Vs Temukan | Xargs:Yang Mana Yang Harus Dipilih?

  1. Mendapatkan Opsi -exec Di Temukan Untuk Bekerja?

  2. Keluar dari Karakter Tidak Dikenal Dari String Untuk -exec?

  3. temukan -exec cmd {} + vs | xargs

  1. temukan -exec fungsi shell di Linux?

  2. Bagaimana cara menemukan path lengkap program C++ Linux dari dalam?

  3. Temukan dan ganti nama direktori