
Ich möchte es so effizient wie möglich machen, falls es viele Dateien gibt. Ich möchte alle gefundenen Dateien umbenennen und ihre Endung entfernen.
Zum Beispiel:
[/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
Das funktioniert nicht. Wenn es eine normale Bash-Variable wäre, ${var%.*}
wäre sie var
bis zum letzten zurückgegeben worden .
.
Antwort1
Starten Sie eine Shell, um Shell-Parametererweiterungsoperatoren zu verwenden:
find ~/tmp -name '*.log' -type f -exec sh -c '
for file do
mv -i -- "$file" "${file%.*}"
done' sh {} +
/tmp
Beachten Sie, dass Sie dies nicht in einem für andere beschreibbaren Verzeichnis tun sollten , da dies böswilligen Benutzern ermöglichen würde, Sie dazu zu veranlassen, beliebige .log
Dateien im Dateisystem¹ umzubenennen (oder Dateien in ein beliebiges Verzeichnis² zu verschieben).
Bei einigen find
und mv
Implementierungen können Sie find -execdir
und verwenden, mv -T
um die Sicherheit zu erhöhen:
find /tmp -name '*.log' -type f -execdir sh -c '
for file do
mv -Ti -- "$file" "${file%.*}"
done' sh {} +
Oder verwenden Sie rename
(die Perl-Variante), die nur einen Systemaufruf ausführt rename()
und nicht versucht, Dateien in andere Dateisysteme oder Verzeichnisse zu verschieben …
find /tmp -name '*.log' -type f -execdir rename 's/\.log$//' {} +
Oder machen Sie das Ganze in perl
:
perl -MFile::Find -le '
find(
sub {
if (/\.log\z/) {
$old = $_;
s/\.log\z//;
rename($old, $_) or warn "rename $old->$_: $!\n"
}
}, @ARGV)' ~/tmp
Beachten Sie jedoch, dass perl
( Find::File
im Gegensatz zu GNU find
) kein sicheres Durchlaufen von Verzeichnissen³ möglich ist. Dies ist also auch bei diesen nichts, was Sie tun möchten /tmp
.
Anmerkungen.
¹ Ein Angreifer kann eine /tmp/. /auth.log
Datei erstellen und zwischen find
dem Suchen und mv
Verschieben (und dieses Zeitfenster kann leicht beliebig groß gemacht werden) das "/tmp/. "
Verzeichnis durch einen symbolischen Link ersetzen, was /var/log
zur /var/log/auth.log
Umbenennung in/var/log/auth
² Viel schlimmer, ein Angreifer kann beispielsweise eine /tmp/foo.log
bösartige Datei und einen symbolischen Link zu dieser Crontab erstellen und Sie dazu bringen, diese zu verschiebencrontab
/tmp/foo
/etc/cron.d
hinein /etc/cron.d
. Das ist die Mehrdeutigkeit mit mv
(gilt auch für cp
und ln
zumindest), die beides sein kannziehen nachUndverschieben in. GNU mv
behebt das Problem mit seinem -t
(hinein) Und -T
(Zu) Optionen.
³ File::Find
durchläuft das Verzeichnis, indem es Folgendes ausführt chdir("/tmp"); read content; chdir("foo") ...; chdir("bar"); chdir("../..")...
. So kann jemand ein /tmp/foo/bar
Verzeichnis erstellen und es im richtigen Moment in umbenennen, /tmp/bar
sodass chdir("../..")
Sie in landen /
.
Antwort2
Hier ist ein Einzeiler:
find /tmp -name "*.log" -type f -exec sh -c 'f="{}"; mv "$f" "${f%.*}"' \;
Es startet eine Shell, weist die {} einer geeigneten Variablen innerhalb der Shell zu und wendet dann die Zeichenfolgenmanipulationen mithilfe der Shell-Syntax an.