從 find -exec 操作 {} 返回字元串
如果有很多文件,我想盡可能高效地執行此操作。我想要的是重命名我找到的所有文件並刪除它們的後綴。
例如:
[/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
到最後一個.
.
啟動一個 shell 以使用 shell 參數擴展運算符:
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
’sFind::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
和移動到的歧義。GNU用它的( into ) 和( to ) 選項來修復它。ln``mv``-t``-T
³
File::Find
通過執行遍歷目錄chdir("/tmp"); read content; chdir("foo") ...; chdir("bar"); chdir("../..")...
。因此,有人可以創建一個/tmp/foo/bar
目錄,並在適當的時候將其重命名/tmp/bar
為.chdir("../..")``/