Hallöchen,
ich hänge etwas an einem kleinen Batch, der mir die älteste Datei
bestimmt in einem Verzeichnis mit diversen Unterverezichnissen bestimmt.
Leider macht er das aber Unterverzeichnisweise. Sprich ich bekomme die
älteste Datei des letzten Verzeichnisses :-(.
Gibt des hier überhaupt eine Lösung via Command Line?
Anbeid er Code:
1
rem älteste Datei bestimmen
2
@echo off
3
for /f %%a in ('dir %sicherung%\cleaner\temp\*.* /tc /s /a-d /b /od') do set oldest=%%a
> Mit einer einzigen Zeile vermutlich nicht lösbar. Muss halt einzeln> überprüft werden.
$ find . -type f -exec ls -l --time-style=+%Y%m%d {} \; | sort -k6,6 |
awk '{print $7}' | head -1
find . geht rekursiv durch alle Unetrverzichnisse und liefert eine
Liste aller Dateien
-type f beschränkt die Suche auf reguläre Dateien
-exec ls führt für jede gefundenen Datei das ls Kommando aus
-l gibt für jede Datei eine 'lange' Liste Eigenschaften aus
*--time-style=+%Y%m%d* setzt das Zeitformat auf YYYYMMDD
*sort -k6,6* sortiert die Liste nach Datum (der sechsten Spalte)
*awk '{print $7}'* druckt aus jeder Zeile die 7. Splte (den Dateinamen)
head -1 selektiert aus der liste die erste Zeile, welche genau die
älteste Datei enthält
Da es explizit um ein Windows System geht, solltest du noch hinzufügen,
woher der OP diese Unix-Ports beziehen kann, wie er sie zum Laufen
bringt und welche spezifische Besonderheiten bei einem gawk, awk oder
der Version aus den SFU zu beachten sind :)
> Da es explizit um ein Windows System geht, solltest du noch hinzufügen,> woher der OP diese Unix-Ports beziehen kann, wie er sie zum Laufen> bringt und welche spezifische Besonderheiten bei einem gawk, awk oder> der Version aus den SFU zu beachten sind :)
Nanu, habe ich da etwas überlesen? Das es Windows sein sollte habe ich
nirgends gefunden. (OK, ich habe mich über die REMs gewundert, aber man
kann ja nicht alle Skriptsprachen kennen ;-) Ich habe den kleinen
Einzeiler aber auf einem Windows XP System getestet, und zwar unter
Cygwin. Also auf http://www.cygwin.com/ die setup-x86.exe herunterladen,
starten, Mirror auswählen, Basissystem installieren, falls eines der
Kommandows fehlt: suchen und nachinstallieren, Terminal öffnen und los
geht’s. Ich installiere Cygwin standardmäßig auf allen meinen Windows
Systemen.
Mir ist da noch eingefallen, dass es ja durchaus mehrere Dateien mit dem
gleichen Zeitstempel geben kann, also muss man als Ergebnis nicht nur
mit einer einzelnen Datei, sondern mit einer Menge rechnen. Die folgende
Version wäre daher vielleicht besser:
Es wäre ja ein fast ein Grund zum Feiern, wenn ein Programm, und sei es
noch so kurz, auf Anhieb fehlerfrei wäre.
Dateinamen mit Leerzeichen wurden nicht korrekt verarbeitet, da der
default delimiter ja ebenfalls ein white space enthält. Betrifft auch
die awk-Variante, so dass token=4 oder {print $7} den gleichen Mist
ergeben.
1
:chkfile
2
rem find oldest file in directory passed by parameter %1
3
rem using dir command sorted by date (last write access)
4
rem and updates olddat, oldfile if older then previous result
5
6
pushd "%~1"
7
8
rem file names may contain blanks so token=4 must not be used directly
9
for /F "usebackq skip=5 tokens=1-3*" %%B in (`dir /A:-D /N /O:D /T:W 2^>NUL`) do (
10
11
rem exit if result doesn't exist as file - caused by dir footer lines
12
rem optional since comparing numerical timestamps using LSS should never fail
13
rem (at least "999999999999" LSS "99999999999A" returns FALSE)
14
if NOT EXIST "%%~E" goto :chkfile_return
15
16
rem rearrange according to local date/time format
17
rem 26.01.200011:33
18
rem 012345678901234
19
set actdat=%%B%%C
20
set actdat=!actdat:~6,4!!actdat:~3,2!!actdat:~0,2!!actdat:~10,2!!actdat:~13,2!
batchman schrieb:> Dateinamen mit Leerzeichen wurden nicht korrekt verarbeitet, da der> default delimiter ja ebenfalls ein white space enthält. Betrifft auch> die awk-Variante, so dass token=4 oder {print $7} den gleichen Mist> ergeben.
Stimmt, solche Dateien habe ich nicht auf meine Rechnern, daher konnte
ich die folgende Version auch nicht testen. Sollte aber gehen:
1
$ find . -type f -exec ls -l --time-style=+%Y%m%d%H%M%S {} \; | sort -k6,6 | sed 1d | awk 'NR==1{time=$6;print}NR!=1{if($6==time)print;else exit}' | sed -r 's/^([^ ]+[ ]){6}//'
Das awk-Skript ist jetzt auch ein bisschen effizienter.
$ find . -type f -exec ls -l --time-style=+%Y%m%d%H%M%S {} \; | sort -k6,6 | awk 'NR==1{time=$6;print}NR!=1{if($6==time)print;else exit}' | sed -r 's/^([^ ]+[ ]){6}//'
Das sed 1d Kommando war nur zum testen drin, um die ersten Dateien mit
gleichem Zeitstempel zu finden. Bei mir waren es die Dateien 2-5, also
musste ich die erste los werden.
ah8 schrieb:> Das awk-Skript ist jetzt auch ein bisschen effizienter.
Ich denke, der Flaschenhals ist nicht awk sondern die find/ls Kombi.
Wenn ich die Rekursion dem ls überlasse und die Auswertung mit awk
nachbaue, ist es sogar etwas schneller als die cmd-Version. Auch mit dem
hiesigen, steinalten cygwin - ls (GNU coreutils) 5.3.0, GNU Awk 3.1.5
anno 2005.
batchman schrieb:> Ich denke, der Flaschenhals ist nicht awk sondern die find/ls Kombi.
Der Meinung würde ich mich anschließen, insbesondere die -exec Option
dürfte teuer sein. Sie startet für jede gefundenen Datei ein neues ls.
Dafür muss sie eigens einen Prozess erzeugen und das Erzeugen von
Prozessen ist für ein Betriebssystem verhältnismäßig aufwendig.
Allerdings mache ich mir meistens nicht die Mühe, solche Einzeiler zu
optimieren. Oft sind sie einfach nur dafür da, mal schnell einen Job zu
erledigen. Da ist es wichtiger, dass sie schnell geschrieben sind als
dass sie schnell laufen. Die Rechenzeit ist schießlich billiger als
meine :-) (Das zusätliche exit bot sich hier einfach nur an.)
Wenn es auf Geschwindigkeit ankommt kann man natürlich auch gleich C
nehmen. Das folgende Beispiel stammt im Wesentlich von K&R (Second
Edition, 1988, Kapitel 8.6: Example – Listing Directories). Ich habe
lediglich die dynamische Speicherverwaltung hinzugefügt und natürlich
die Aktion für die gefundenen Dateien angepasst. Die Optionen sind als
Beispiel für Modifikationen gedacht. Läuft auch unter cygwin (gcc 4.8.2)
und sollte keine Probleme mit Leerzeichen machen :-)