Sortieren Sie die Ausgabe von find -exec ls


14

Ist es möglich, die Ausgabe find … -exec ls -ls ;alpabetisch zu sortieren, nach Dateinamen?

Dies ist mein Cron-Befehl:

find /home/setefgge/public_html -type f -ctime -1 -exec ls -ls {} \;

Dieser Befehl funktioniert größtenteils in Ordnung. Die Ergebnisse sind jedoch nicht in einer sinnvollen Reihenfolge sortiert. Es wäre sehr hilfreich, wenn sie nach dem Dateinamenfeld sortiert wären.


1
Verwenden Sie zsh? ls -ls **/*(.)
Kevin

@ Kevin Nicht ganz - lswürde sortieren.
Gilles 'SO- hör auf böse zu sein'

Antworten:


14

Ich gehe davon aus, dass Ihre Dateinamen keine Zeilenumbrüche enthalten.

find /home/setefgge/public_html -type f -ctime -1 -exec ls -nls {} + | sort -k 10

Wenn Sie die Aktion beenden, +anstatt sie ;zu verwenden, -execwird sie durch Stapeln der Aufrufe von beschleunigt ls. Sie können sortieren, indem Sie den sortBefehl weiterleiten. Sagen Sie ihm, dass er beim 10. Feld mit dem Sortieren beginnen soll (die ersten 9 sind die Metadaten: Blöcke, Berechtigungen, Linkanzahl, Benutzer, Gruppe, Größe und 3 Datums- / Zeitfelder). Die Option -nsagt lsnumerische Werte für den Benutzer und die Gruppe zu verwenden, die das Risiko von Benutzer- oder Gruppennamen vermeidet enthält Leerzeichen.

Alternativ dazu können Sie mit zsh ohne jede Annahme eines Namens davonkommen, indem Sie Glob-Qualifikationsmerkmale verwenden , um die Dateien zu sammeln und zu sortieren und mehrmals zargsauszuführen, lswenn die Befehlszeile zu lang wäre. Du brauchst GNU ls(speziell seine -fOption), um eine Neu-Sortierung zu vermeiden ls(ein anderer Ansatz wäre, lsmit zshs zu emulieren zstat).

autoload -U zargs
zargs -- /home/setefgge/public_html/**/*(.c-2) -- ls -lnsf

Ich danke dir sehr! Mit dem ersten Befehl, den Sie gesendet haben, wird die Sortierung durchgeführt. Wäre die Zahl immer noch 10, wenn ich einen kürzeren Pfad verwenden würde? Wenn ich zum Beispiel den gleichen Befehl aus / home / setefgge anstelle von public_html ausführe?
4.

@MaJ 10 ist die Anzahl der übersprungenen Felder und hat nichts mit der Größe des Dateinamens zu tun.
Gilles 'SO- hör auf böse zu sein'

Vielen Dank. Ich danke Ihnen und allen anderen für Ihre Hilfe. Ich halte dieses Problem für gelöst. Mein Cron-Befehl sortiert jetzt die Dateien. Dies ist das erste Mal, dass ich eine Frage an Stackexchange stelle. Ich sehe keine "Gelöste" Option. Wenn jemand von euch weiß, wie man das als gelöst postet, macht bitte weiter. Vielen Dank!
5.

@MaJ Das Nächste, was wir tun müssen, um eine Frage als gelöst zu markieren, ist, eine der Antworten als akzeptiert zu markieren. Das können nur Sie, der Fragesteller. Klicken Sie dazu auf das Häkchen neben der Antwort, die Ihnen am meisten geholfen hat. Wenn Sie eine Antwort akzeptieren, erhalten Sie zwei weitere Reputationspunkte. Danach können Sie Posts positiv bewerten. Sie können alle Beiträge, die Sie hilfreich fanden, positiv bewerten. Weitere Informationen finden Sie auf der Tour-Seite und auf der Hilfeseite, was zu tun ist, wenn jemand Ihre Frage beantwortet .
Gilles 'SO- hör auf böse zu sein'

1

Warum nicht das Ergebnis von find through sort leiten und dann ls für jede der Zeilen ausführen?

find . -type f -ctime -1 | sort | while IFS= read -r filename; do ls -ls "$filename"; done

1

POSIX hat Folgendes zu Terminen in einer ls -lListe zu sagen :

Das <date and time>Feld muss das Datum und den Zeitstempel der letzten Änderung der Datei enthalten. Im POSIX-Gebietsschema entspricht das Feld der Ausgabe des folgenden Datumsbefehls:

date "+%b %e %H:%M"

... wenn die Datei in den letzten sechs Monaten geändert wurde oder:

date "+%b %e %Y"

In Anbetracht dessen und um sicherzustellen, dass Zeilenumbrüche in einem Dateinamen mit der ebenfalls von POSIX angegebenen ls -qOption ordnungsgemäß entfernt werden , ist es relativ einfach, einen regulären Ausdruck für ein lsErgebnis zu erstellen, ohne dass find:

d=$(date "+%b %e") y=$(date --date=yesterday "+%b %e")
echo "$d" "$y"

###OUTPUT###
Jul  5 Jul  4

grepdafür und Sie werden nur Zeilen zurückgeben, die die Zeichenfolgen enthalten, die entweder das heutige oder das gestrige Datum darstellen. Der folgende Befehl fügt dem ein wenig hinzu:

ls -alRcq | sed "1H;/^-/!{/./d;N;h};/$d\|$y/!d;x;/\n/p;g"

ls Optionen bestehen aus:

  1. -a Alle Dateien in einem Verzeichnis zurückgeben - einschließlich der Dateien, die mit einem beginnen .dot
  2. -l lange Liste
  3. -R Listen Sie alle untergeordneten Verzeichnisse rekursiv auf
  4. -c Änderungszeit anstatt Zugriffszeit anzeigen
  5. -qGeben Sie das Shell-Glob zurück, ?anstatt nicht druckbare oder \tab-Zeichen in einem Dateinamen

Diese Ergebnisse werden über die |pipeDatei übertragen, für seddie nur Folgendes zutrifft:

  1. Die leere Zeile vor einem Pfadnamen und die folgende Zeile
  2. Zeilen, die mit - (also nicht dfür Verzeichnisse) beginnen und auch Ihre enthalten date.
  3. Die Pfadnamenzeilen werden jedoch nicht gedruckt, es sei denn, das von ihnen angegebene Verzeichnis enthält tatsächlich Dateien, nach denen Sie gefiltert haben.

Die Ausgabe sieht folgendermaßen aus:

ls -alRcq --color=always | 
sed "1H;/^-/!{/./d;N;h};/$d\|$y/!d;x;/\n/p;g"

###OUTPUT###
.:
-rw------- 1 mikeserv mikeserv   2086 Jul  4 10:52 .bash_history
-rw------- 1 mikeserv mikeserv   2657 Jul  4 15:20 .lesshst
-rw-r--r-- 1 mikeserv mikeserv    681 Jul  5 05:18 .zdirs
-rw------- 1 mikeserv mikeserv 750583 Jul  5 08:28 .zsh_history
-rw-r--r-- 1 mikeserv mikeserv    166 Jul  4 23:02 Terminology.log
-rw-r--r-- 1 mikeserv mikeserv 433568 Jul  4 13:34 shot-2014-06-22_17-10-16.jpg
-rw-r--r-- 1 mikeserv mikeserv 445192 Jul  4 13:34 shot-2014-06-22_17-11-06.jpg

./.cache/efreet:
-rw------- 1 mikeserv mikeserv  37325 Jul  4 22:51 desktop_localhost_C.eet
-rw------- 1 mikeserv mikeserv  37325 Jul  4 23:30 desktop_localhost_en_US.eet
-rw------- 1 mikeserv mikeserv  24090 Jul  4 22:51 desktop_util_localhost_C.eet
-rw------- 1 mikeserv mikeserv  24090 Jul  4 23:30 desktop_util_localhost_en_US.eet
-rw------- 1 mikeserv mikeserv  16037 Jul  4 23:30 icon_themes_localhost.eet
-rw------- 1 mikeserv mikeserv   3117 Jul  4 23:30 icons___efreet_fallback_localhost.eet
-rw------- 1 mikeserv mikeserv 768039 Jul  4 23:30 icons_gnome_localhost.eet
-rw------- 1 mikeserv mikeserv  18589 Jul  4 23:30 icons_hicolor_localhost.eet

./.config:
-rw-r--r-- 1 mikeserv mikeserv   30 Jul  4 19:10 pavucontrol.ini

./.config/chrome:
-rw-r--r-- 1 mikeserv mikeserv 94332179 Jul  4 13:36 conf.tar.lz4.bak

Ja, es funktioniert sogar mit LS_COLORS- was für Sie cronnatürlich wahrscheinlich eine niedrige Priorität hat , aber Ihre Optionen sind offen.

In jedem Fall bietet dies einige wesentliche Vorteile gegenüber einigen anderen möglichen Lösungen.

  1. Erstens beinhaltet find+ lsmehrere Aufrufe - dies betrifft nur einen einzigen lsProzess, und deshalb ist es in der Lage, alles zuverlässig zu sortieren - was es standardmäßig tut - und wird daher sortauch zur Nebensache gemacht.

  2. Jede Lösung beteiligt findund sortund lsist ziemlich viel zu tun all die Arbeit zweimal. lsund findwird sowohl jeden Pfadnamen als auch statjede Datei auflösen . lsund sortwerden beide alle Ergebnisse sortieren. Es ist wahrscheinlich am besten, nur die Single zu verwenden ls.

  3. Dann gibt es natürlich die dateund sedTeile dieser Antwort. Das Wichtigste dabei ist, dass Sie den schwierigen Teil erledigen und den regulären Ausdruck zuerst - und nur einmal - abrufen und anschließend nur eine einzelne Liste von Ergebnissen beschneiden, anstatt zu sagen, Ergebnisse abzurufen, Ergebnisse abzurufen, Ergebnisse zu sortieren und Ergebnisse zu sortieren.

  4. Dies funktioniert nicht bei Dateinamen, die Zeilenumbrüche enthalten, wie dies bei anderen Lösungen wahrscheinlich der Fall sein wird. Diese Lösung hat ihre eigenen Vorbehalte - die ich als nächstes erkläre - aber sie sind winzig und leicht zu handhaben. Meiner Meinung nach ist dies die robusteste Lösung hier.

Es gibt zwei Fälle, in denen der obige Befehl Probleme verursachen kann. Das erste ?Problem betrifft die Globs in den Dateinamen. Da es sich bereits um eine robustere Lösung als alle anderen hier angebotenen handelt und die Wahrscheinlichkeit, dass Sie überhaupt auf einen stoßen, ?gering genug ist, besteht die Möglichkeit, dass diese Globs aufgelöst werden könnte mit mehr als einem Dateinamen übereinstimmen. Bitte beachten Sie dies , um weitere Informationen zu diesem Thema.

Die andere Möglichkeit ist ein falsches Positiv - zum Beispiel, wenn Sie einen Dateinamen haben, der tatsächlich mit der dateZeichenfolge übereinstimmt, mit der wir suchen, der grepaber an keinem dieser Tage tatsächlich geändert wurde. Ich zähle nicht darauf, dass dies ein Problem ist, aber wenn ja, fragen Sie danach, und ich kann Ihnen wahrscheinlich dabei helfen, die Regex zu präzisieren, um damit umzugehen.


0

Sie können tatsächlich eine Kombination aus find, xargs und ls verwenden.

Hier ist ein Beispielbefehl: find . -type f -print0 | xargs -0 ls -lt

  • find sucht rekursiv nach allen Dateien im aktuellen Verzeichnis.
  • xargs übergibt diese Dateiliste lsin einem einzigen Aufruf an den Befehl (sofern findweniger als ARG_MAXDateien zurückgegeben werden).
  • ls -lt sortiert diese Dateien nach Zeit und formatiert die Ausgabe

Um Ihr System abzurufen, können ARG_MAXSie Folgendes eingeben:

$ getconf ARG_MAX
> 2621440

-1
ls -l $(find /home/setefgge/public_html -type f -ctime -1 | sort)

1
lsSorgt für eine eigene Sortierung, sodass die Ausgabe von findThrough sortunbrauchbar ist. Außerdem werden durch Ihren Befehl Dateinamen, die (unter anderem) Leerzeichen enthalten, unleserlich gemacht, und es treten Fehler auf, wenn zu viele Dateinamen vorhanden sind.
Gilles 'SO- hör auf böse zu sein'
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.