Kann ich aus einem Bash-Glob nur ein Ergebnis auswählen?

14

Ich versuche, ein Skript für die Arbeit zu schreiben, um einige Berichte für eine Ausgabe zu automatisieren. Die Protokolldateien werden (derzeit wird sie in Zukunft standardisiert) in dieser Art von Pfadstruktur gespeichert:

/<root_path>/<process_one_path>/logs/<time_date_stamp>/<specific_log_file>

/<root_path>/<process_two_path>/logs/<different_time_date_stamp>/<specific_log_file>

Jeder Teil des Pfads ist bekannt, mit Ausnahme der Zeitstempel, die immer die neuesten im Ordner sind.

Wenn ich versuche, anstelle des Zeitstempels einen Platzhalter zu verwenden, erhalte ich mehrere Ergebnisse, z.

> ls /<root_path>/<process_two_path>/logs/* [tab]
20130102-175103
20130118-090859
20130305-213506

Ich möchte nur, dass es das neueste zurückgibt. Ist das mit Bash möglich?

NB (Ich habe kein zsh, und so schön es klingt, ich bezweifle, dass wir es jemals bei der Arbeit bekommen werden.)

Pureferret
quelle

Antworten:

9

Die folgenden Arbeiten in Bash 4.2:

list=( /<root_path>/<process_two_path>/logs/* )
echo "${list[-1]}"

Wenn Ihre Bash eine ältere Version ist:

list=( /<root_path>/<process_two_path>/logs/* )
echo "${list[${#list[@]}-1]}"
Patrick
quelle
Das funktioniert definitiv auf meinem Heimcomputer, aber ich kann nicht garantieren, dass es bei der Arbeit funktioniert?
Pureferret
@Pureferret Der Teil, der möglicherweise nicht funktioniert, ist der negative Array-Index ( -1). Dies wurde in Bash 4.2 hinzugefügt. RHEL5 ist wahrscheinlich die älteste unterstützte Hauptdistribution für Unternehmen und verwendet Bash 4.2.20.
Patrick
1
Ältere Versionen von bashhaben: "${list[@]: -1}"wie in ksh93( [-1]kommt von zsh).
Stéphane Chazelas
@Patrick - RHEL5 verwendet Bash 3.2. RHEL 3 und 4 werden noch über längere Zeit unterstützt.
Jordan
1
@Pureferret Du kannst auch mit der Arraylänge rechnen, siehe meine Bearbeitung.
Gilles 'SO- hör auf böse zu sein'
10

POSIXly:

 set -- /<root_path>/<process_two_path>/logs/*
 shift "$(($# - 1))"
 printf '%s\n' "$1"

Da erwähnen Sie zsh:

 print -r /<root_path>/<process_two_path>/logs/*([-1])
Stéphane Chazelas
quelle
4

Verwenden Sie den Bash-Glob in einer Bash-for-Schleife. So was:

for filename in <logdir>/*; do :; done; echo "$filename"

Dies hängt davon ab, dass Bash die Glob-Erweiterung alphabetisch sortiert. Lesen Sie das Bash-Handbuch für weitere Informationen. Beachten Sie, dass dies von LC_COLLATE abhängt . Dies hängt auch davon ab, dass die Variable filenamenach Beendigung der Schleife noch den letzten Wert enthält.

Wenn Sie den Dateinamen mit dem ältesten Zeitstempel haben möchten, können Sie dies folgendermaßen tun:

for filename in <logdir>/*; do echo "$filename"; break; done
Lesmana
quelle
1

-1 ist die Standardeinstellung in Pipelines, und die ls-Ausgabe sollte bereits sortiert sein:

ls | tail -n1

Wenn andere Benutzer das erste oder letzte Ergebnis interaktiv einfügen möchten, können Sie in .inputrc menu-complete oder menu-complete-backward binden:

"\e\t": menu-complete
"\e[Z": menu-complete-backward # shift-tab

Wenn Show-All-If-Ambiguous aktiviert ist, set completion-query-items 0wird die Eingabeaufforderung entfernt, wenn 101 oder mehr Ergebnisse set page-completions offvorliegen, und der Pager wird deaktiviert.

Lri
quelle