Ich habe diese Situation, in der es viele Dateien mit ähnlichen Namen (aber sie folgen alle einem Muster) in verschiedenen Unterordnern gibt
file1
file1 (Copy)
/folder1/file2.txt
/folder1/file2 (Copy).txt
/folder1/file3.png
/folder1/file3 (Copy).png
Jede Datei befindet sich im selben Ordner wie ihre Kopie und hat dieselbe Erweiterung. Der Unterschied besteht darin, dass sie (Copy)
am Ende des Namens
Ich möchte alle diese Dateien abrufen und die älteste löschen und die Datei anschließend, falls eine Umbenennung erforderlich ist, von beispielsweise in umbenennen (das heißt, das Suffix file1 (Copy)
entfernen file1
) .(Copy)
Ich habe überlegt, find
und zu verwenden mv
, bin mir aber nicht sicher, wie ich ihm sagen kann, dass es das Aktuellste verschieben soll.
Antwort1
Erweitertfind
+bash
Lösung (benötigt auch die GNU-Implementierung von stat
):
find . -type f -name "* (Copy).*" -exec bash -c 'p="${0%/*}"; bn="${0##*/}";
main_bn="${bn/ (Copy)/}";
if [ -f "$p/$main_bn" ]; then
t_copy_file=$(stat -c %Y "$0"); t_main_file=$(stat -c %Y "$p/$main_bn");
if [[ $t_copy_file -gt $t_main_file ]]; then
mv "$0" "$p/$main_bn";
else
rm "$0";
fi;
fi' {} \;
p="${0%/*}"
- Dateipfad/Pfad mit gekürztem Basisnamenbn="${0##*/}"
- Basisname der Dateimain_bn="${bn/ (Copy)/}"
- Entfernen Sie(Copy)
einen Teilstring aus dem Basisnamen, um denHaupt-/gemeinsameBasisnameif [ -f "$p/$main_bn" ]
- wenn dieHaupt-/OriginalDatei existiert (und wird nach der Symlink-Auflösung als reguläre Datei erkannt)t_copy_file=$(stat -c %Y "$0")
- Letzte Änderungszeit des gefundenen Objekts abrufen"Kopieren"Dateit_main_file=$(stat -c %Y "$p/$main_bn")
- Letzte Änderungszeit abrufen vonOriginalDateiif [[ $t_copy_file -gt $t_main_file ]]
- wenn die"Kopieren"Datei ist die neueste - verschieben Sie sie in dieOriginaleins (mach esOriginal) mitmv "$0" "$p/$main_bn"
- ansonsten derOriginalDatei ist die neueste, entfernen Sie "Kopieren" Datei mit
rm "$0"
Oder etwas kürzer mit -nt
dem Dateitestoperator ( [ newerfile –nt olderfile ]
- prüfen, ob newerfile
es neueren Datums ist als olderfile
, oder ob newerfile
es existiert, aber olderfile
nicht):
find . -type f -name "* (Copy).*" -exec bash -c 'p="${0%/*}"; bn="${0##*/}";
main_bn="${bn/ (Copy)/}";
if [ -f "$p/$main_bn" ]; then
if [ "$0" -nt "$p/$main_bn" ]; then
mv "$0" "$p/$main_bn";
else
rm "$0";
fi;
fi' {} \;
Antwort2
Möglicherweise ist es einfacher mit zsh
:
setopt extendedglob # best in ~/.zshrc
for file (./**/?*" (Copy)"*(ND.)) {
base=$file:h/${${file:t}/" (Copy)"}}
[[ ! -f $base || -L $base ]] ||
if [ $file -nt $base ]; then
mv $file $base
else
rm -f $file
fi
}
Möglicherweise möchten Sie zunächst überprüfen, ob keine file (Copy) (Copy).txt
Dateien vorhanden sind.
**/
: jede UnterverzeichnisebeneN
:nullglobexpandieren, wenn es keine Übereinstimmung gibt, anstatt einen Fehler zu verursachenD
: Einschließen versteckter Dateien (D
oder Dateien) und Absteigen in versteckte Verzeichnisse..
: nur einschließenregulärDateien (kein Verzeichnis, FIFO, Gerät, symbolischer Link …)$file:h
:Kopfder Datei (Verzeichnisteil), wie incsh
$file:t
:Schwanz(Dateiname Teil)${var/pattern/replacement}
, hier ohne Ersatz[[ ! -f $base || -L $base ]] ||...
Überspringen Sie als Sicherheitsmaßnahme nicht reguläre Dateien oder symbolische Links (auch wenn sie auf reguläre Dateien verweisen).[ $file -nt $base ]
: gibt „true“ zurück, wenn$file
zuletzt geändert wurdenach$base
(oder$base
nicht zugänglich ist, sollte dies nach der obigen Prüfung nicht passieren).