Ich habe mir eben mal den Spaß gemacht, den Befehl einigermaßen sonderzeichensicher zu machen. Das Resultat:
cp "$(find ipcamtest/front/cam1 -type f -printf "%T@\t%p\0" | sort -zn | tail -zn 1 | cut -z -f 2-)" front.jpg
Bevor ich zur Erläuterung übergehe, hier noch ein Link, auf einen Artikel, in dem erklärt wird, warum man die Ausgabe von ls
in der Regel nicht verarbeiten sollte: Link 🇬🇧. Zusammenfassung: Unix/Linux erlauben so ziemlich jedes Zeichen in Dateinamen und ls
gibt diese nicht immer so aus, dass weiterverarbeitende Programme diese korrekt verarbeiten können, was zu Fehlern und Datenverlusten führt.
Und noch eine Anmerkung zum Sortieren im ursprünglichen Post: Da
die Dateien so sortiert, dass die neueste am Anfang steht, hätte statt tail
auch head
die Arbeit übernehmen können. Damit würde das Umkehren der Liste mit -r
entfallen. ☺
Erläuterung:
"$(...)"
startet die bereits von user_unknown angedeutete Subshell - hier umgeben von doppelten Anführungszeichen, um auch Rückgabewerte (also Dateinamen) mit Leerzeichen oder Zeilenumbrüchen verarbeiten zu können. In dieser Subshell wird eine Befehlspipeline ausgeführt, die die Ausgaben von find, sort, tail und cut so verarbeitet, dass am Ende der Name (und Pfad relativ zum Startpunkt der find-Suche) der neuesten gefundenen Datei mitsamt sämtlicher Besonderheiten zurückgegeben wird.
Die verlinkten Wikiseiten geben im Gegensatz zu den manpages keine Auskunft über den fast durchgehend benutzten Schalter -z
aus. Dieser Schalter bewirkt, dass die Programme nicht die normale Zeilenschaltung (\n
) betrachten, sondern ASCII NUL, welches in Unix/Linux eine besondere Bedeutung hat (z.B. ist es eines der wenigen Zeichen, die nicht in Dateinamen vorkommen dürfen).
Nun zum ersten Teil der Pipeline, dem find
-Befehl. Er sucht alle Dateien im angegebenen Verzeichnis und gibt das Ergebnis formatiert (-printf
) aus. Der Formatstring bedeutet:
%T@ Zeitpunkt der letzten Änderung als Anzahl der Sekunden seit dem 01.01.1970, 00:00 GMT
\t Tabulator (später für cut verwendet)
%p Dateiname
\0 NUL (Trennzeichen für Suchergebnisse)
In den nächsten beiden Schritten wird der Suchergebnissatz numerisch aufsteigend sortiert und die letzte Zeile der sortierten Liste an cut
übergeben.
cut
unterteilt eine Zeile in mehrere Felder (-f
), wobei das Standardtrennzeichen der Tabulator ist. Wir hätten im find
-Befehl auch ein anderes Zeichen setzen und dieses an cut
mit der Option -d 'DELIM'
übergeben können. Am Ende wählen wir mittels -f 2-
alle Felder beginnend ab Feld 2 aus. Der Hintergrund ist der, dass wir dann auch korrekte Dateinamen zurückgeben können, die ein Tabulatorzeichen beinhalten und wir wissen, dass im ersten Feld nur der bekannte Zeitstempel steht, den wir nur zum Sortieren brauchten.
Beim Zusammenstellen der Lösung geholfen haben mir: