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 .