Ich möchte es so effizient wie möglich machen, falls es viele Dateien geben wird.
Ich möchte alle Dateien, die ich gefunden habe, umbenennen und ihr Suffix 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 war ${var%.*}
hätte var
zurückgegeben bis zum letzten .
.
Akzeptierte Antwort:
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 {} +
Beachten Sie, dass Sie dies nicht auf /tmp
tun möchten oder jedes Verzeichnis, das von anderen beschreibbar ist, da dies böswilligen Benutzern ermöglichen würde, Sie dazu zu bringen, beliebige .log
umzubenennen Dateien im Dateisystem¹ (oder verschieben Sie Dateien in ein beliebiges Verzeichnis²).
Mit etwas find
und mv
Implementierungen können Sie find -execdir
verwenden und mv -T
um es sicherer zu machen:
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 ein rename()
ausführen würde Systemaufruf, also versuchen Sie nicht, Dateien in andere Dateisysteme oder in 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
’s Find::File
(im Gegensatz zu GNU find
) führt kein sicheres Verzeichnis-Traversal³ durch, also möchten Sie das auf /tmp
nicht tun entweder.
Notizen.
¹ Ein Angreifer kann einen /tmp/. /auth.log
file, und dazwischen find
finden und mv
Wenn Sie es verschieben (und dieses Fenster kann leicht beliebig groß gemacht werden), ersetzen Sie den "/tmp/. "
Verzeichnis mit einem symbolischen Link zu /var/log
was zu /var/log/auth.log
führt umbenannt in /var/log/auth
² Schlimmer noch, ein Angreifer kann eine /tmp/foo.log
erstellen bösartiges crontab
zum Beispiel und /tmp/foo
ein symbolischer Link zu /etc/cron.d
und lassen Sie diese Crontab in verschieben /etc/cron.d
. Das ist die Mehrdeutigkeit bei mv
(gilt auch für cp
und ln
zumindest), das kann beides sein move to und einziehen . GNU mv
behebt es mit seinem -t
(in ) und -T
(nach ) Optionen.
³ File::Find
durchläuft das Verzeichnis mit chdir("/tmp"); read content; chdir("foo") ...; chdir("bar"); chdir("../..")...
. Also kann jemand einen /tmp/foo/bar
erstellen Verzeichnis und benennen Sie es im richtigen Moment in /tmp/bar
um also der chdir("../..")
würde Sie in /
landen .