Wie liste ich Dateien auf, die in einem bestimmten Zeitraum geändert wurden?

38

Wie kann ich alle Dateien, die zwischen dem 22.12.2011 und dem 24.12.2011 geändert wurden, rekursiv auflisten?

Klemme
quelle
6
Wenn Sie "zuletzt geändert" meinen, haben Sie eine Chance auf eine Lösung. Wenn eine Datei am 26.12.2011 geändert wurde, können Sie nicht feststellen, ob sie in dem von Ihnen angegebenen Bereich geändert wurde. (Es sei denn, Sie haben ein sehr exotisches Dateisystem.)
William Pursell

Antworten:

25

Wenn Sie Dateien in einem Verzeichnis und seinen Unterverzeichnissen rekursiv suchen, verwenden Sie im Allgemeinen find.

Die einfachste Möglichkeit, einen Datumsbereich anzugeben, findbesteht darin, Dateien an den Bereichsgrenzen zu erstellen und das -newerPrädikat zu verwenden.

touch -t 201112220000 start
touch -t 201112240000 stop
find . -newer start \! -newer stop
Gilles 'SO - hör auf böse zu sein'
quelle
Warum muss hier die Ausgabe der ersten negiert -newerwerden?
Alexander Cska
@AlexanderCska Der erste -newerwird nicht negiert, der zweite ist. "Dateien suchen, die neuer als, startaber nicht neuer als sind stop".
Gilles 'SO- hör auf böse zu sein'
Ok Negation funktioniert bei dem Befehl danach. Was würde passieren, wenn keine Verneinung vorhanden wäre?
Alexander Cska
@AlexanderCska Dann würden Sie die Dateien erhalten, die neuer als beide startund sind stop.
Gilles 'SO - hör auf böse zu sein'
35

Unter Verwendung von Gilles 'Lösung und nachdem ich den man find (1) wieder gelesen hatte, fand ich eine einfachere Lösung. Die beste Option ist -newerXY. Die Flags m und t können verwendet werden.

m   The modification time of the file reference
t   reference is interpreted directly as a time

Die Lösung ist also

find . -type f -newermt 20111222 \! -newermt 20111225

Die Untergrenze inklusiv und die Obergrenze ist exklusiv, also habe ich 1 Tag hinzugefügt! Und es ist rekursiv. Es funktioniert gut mit find v4.5.9.

TrueY
quelle
Cooler Trick, danke! Das hat mir geholfen, eine aktuelle Datei zu finden, die ein bestimmtes Schlüsselwort in einem Verzeichnis mit Tausenden von Dateien enthält: find -newermt 20150212 \! -newermt 20150213 | xargs grep 'keyword' -m 50 -l( -m 50= Suche in den ersten 50 Zeilen).
Rob W
@RobW: Eigentlich kann man das Rohr und xargs verschonen mit -exec ... +in find(1), wie: find -newermt 20150212 \! -newermt 20150213 -exec grep keyword -m 50 -l {} +. Dies funktioniert genauso, ist aber billiger.
TrueY
Ich musste die Zeitstempel in doppelte Anführungszeichen setzen (ich bin auf Ubuntu Xenial mit find 4.7.0-git).
IsaacS
13

Beachten Sie zusätzlich zu den bereits gegebenen Antworten, dass Sie Ihre Daten direkt angeben können:

find -type f -newermt "2011-12-22" \! -newermt "2011-12-24"

oder

find -type f -newermt "2011-12-22 00:00:00" \! -newermt "2011-12-24 13:23:00"

wenn Sie zusätzlich die Uhrzeit angeben möchten.

Schüler
quelle
6

Vorausgesetzt, Sie benötigen keine sekundengenaue Genauigkeit, sollte dies funktionieren.

find . -type f -mmin -$(((`date +%s`-`date -d 20111222 +"%s"`)/60)) \! -mmin +$(((`date +%s`-`date -d 20111224 +"%s"`)/60))

EDIT: Changed cminbis mminnach @ Eelvex Kommentar. BEARBEITEN: '\!' fehlt

onur güngör
quelle
hm scheint nicht zu funktionieren. Sind Sie sicher, dass es die Unterverzeichnisse rekursiv durchläuft?
Klemme
Ja, es funktioniert bei mir. Haben Sie wirklich Dateien in diesem Zeitraum geändert? Probieren Sie es mit verschiedenen Zeitbereichen.
Onur Güngör
6
-cminist "Statusänderung", -mminist "Datenänderung". Sie wollen wahrscheinlich-mmin
Eelvex
3

findkann eine ISO-formatierte Datums- / Uhrzeitangabe annehmen, sodass Sie beispielsweise für einen UTC-Server einen Zeitversatz von mehreren Stunden angeben können, von dem aus Sie sich gerade befinden. Dadurch muss auch ein Tag hinzugefügt werden, da Sie auch die Zeit vergleichen:

find -type f -newermt 20111224T0800 \! -newermt 20111225T0800
Alex Young
quelle
0

Bitte beachten Sie, dass die als Duplikat markierte Frage nicht direkt beantwortet werden kann. Deshalb poste ich hier. Diese Antwort dient zur Beantwortung der Frage "Dateien müssen je nach Erstellungsdatum in einen anderen Ordner verschoben werden [duplizieren]".

Die Antworten sind vernünftig, aber es gab einige Einschränkungen bei einem reinen Suchbefehl. Ich habe dieses Shell-Skript geschrieben, um durch ein Verzeichnis mit so vielen Dateien zu gehen, dass das Dateisystem die Metadaten abfragt, um ein ls auszuführen. Außerdem wird auf einigen * nix-Systemen beim Ausführen von ls ein Fehler mit zu vielen Argumenten angezeigt.

Der Befehl find ist sehr mächtig und ich habe mit den aufgelisteten Methoden begonnen, aber ich hatte so viele Jahre an Daten in diesem Verzeichnis, dass ich alle Dateien wiederholt durchlaufen musste. Dies erzeugt eine Menge unnötiger Übergänge über jede Datei. Ich habe versucht, einen Bildschirm pro Jahr zu erstellen und mehrere Suchvorgänge auszuführen. Dies führte jedoch zu vielen Fehlern bei den einzelnen Suchvorgängen, und Dateien gingen verloren, wenn einer der Suchvorgänge verschoben wurde.

Mein Shell-Skript verschiebt eine Datei mit einem vierstelligen Jahr und einem zweistelligen Monat in das Zielverzeichnis. Es kann leicht auf einen zweistelligen Tag erweitert werden, indem ein paar Zeilen auskommentiert und ihre Gegenstücke auskommentiert werden. Ich glaube, es ist effizienter, weil es die Bewegungen in einem Durchgang der Suche durchgeführt hat, so dass mehrere Suchbefehle und Durchgänge über das Verzeichnis nicht erforderlich sind.

#!/bin/bash
#We want to exit if there is no argument submitted
if [ -z "$1" ]
then
  echo no input file
  exit
fi

#destDir should be set to where ever you want the files to go
destDir="/home/user/destination"

#Get the month and year of modification time
#--format %y returns the modification date in the format:
# 2016-04-26 12:40:48.000000000 -0400
#We then take the first column, split by a white space with awk
date=`stat "$1" --format %y | awk '{ print $1 }'`

#This sets the year variable to the first column split on a - with awk
year=`echo $date | awk -F\- '{print $1 }'`
#This sets the month variable to the second column split on a - with awk
month=`echo $date | awk -F\- '{print $2 }'`
#This sets the day variable to the third column split on a - with awk
#This is commented out because I didn't want to add day to mine
#day=`echo $date | awk -F\- '{print $3 }'`

#Here we check if the destination directory with year and month exist
#If not then we want to create it with -p so the parent is created if
# it doesn't already exist
if [ ! -d $destDir/$year/$month ]
then
  mkdir -p $destDir/$year/$month || exit
fi

#This is the same as above but utilizes the day subdirectory
#Uncommented this out and comment out the similar code above
#if [ ! -d $destDir/$year/$month/$day ]
#then
#  mkdir -p $destDir/$year/$month$day || exit
#fi

#Echoing out what we're doing
#The uncommented is for just year/month and the commented line includes day
#Comment the first and uncomment the second if you need day
echo Moving $1 to $destDir/$year/$month
#echo Moving $1 to $destDir/$year/$month/$day

#Move the file to the newly created directory
#The uncommented is for just year/month and the commented line includes day
#Comment the first and uncomment the second if you need day
mv "$1" $destDir/$year/$month
#mv "$1" $destDir/$year/$month/$day

Einmal gespeichert und ausführbar gemacht, können Sie dieses Skript mit find wie folgt aufrufen.

find /path/to/directory -type f -exec /home/username/move_files.sh {} \;

Sie müssen sich nicht um die Einstellung der Option newermt für find kümmern, da find nur eine Ausführung pro gefundener Datei bereitstellt und das Skript alle Entscheidungen trifft.

Denken Sie daran, dass, wenn Sie -type f nicht auswählen, Verzeichnisse verschoben werden und dies wahrscheinlich Probleme verursacht. Sie können auch -type d verwenden, wenn Sie nur Verzeichnisse verschieben möchten. Wenn Sie den Typ nicht festlegen, wird dies mit ziemlicher Sicherheit zu unerwünschtem Verhalten führen.

Denken Sie daran, dass dieses Skript auf meine Bedürfnisse zugeschnitten wurde. Vielleicht möchten Sie einfach mein Konstrukt als Inspiration für ein für Ihre Bedürfnisse besser geeignetes Skript verwenden. Danke!

Überlegungen: Die Effizienz des Befehls kann erheblich verbessert werden, indem eine unbegrenzte Anzahl von Argumenten durch das Skript geleitet wird. Dies ist relativ einfach, wenn Sie die Variable $ @ übergeben. Wenn Sie die Funktionalität erweitern, können Sie beispielsweise die Funktion -exec + von find verwenden oder xargs nutzen. Ich kann das schnell umsetzen und meine eigene Antwort verbessern, aber das ist ein Anfang.

Da dies eine einmalige Skriptsitzung war, können wahrscheinlich viele Verbesserungen vorgenommen werden. Viel Glück!

Vex Magier
quelle