
Ich habe ein Bash-Skript namens findme
, das wie folgt codiert ist:
#!/bin/bash
locate -Abi '*\.'$1 $2 | grep --color=always -ni $2 | less -R
Es sucht für mich nach allen Dateien mit einer bestimmten Dateierweiterung (erstes Argument, das dem Skript übergeben wird), die ein Muster (das nächste übergebene Argument) im Dateinamen haben.
Wenn ich Folgendes ausführe:
user@machine$ findme pdf classifi
pdf
Es wird nach allen Dateien gesucht, die classifi
den Dateinamen enthalten. Ich erhalte also möglicherweise das folgende Ergebnis.
1:/home/Benutzer/Dropbox/SharedWithFriends/math/klassifizierenkationen2000.pdf
2:/home/Benutzer/Dropbox/SharedWithFriends/math/klassifizierenkationen2010.pdf
Die Frage ist: „Können Sie mir einen Bash-Skriptcode geben, der mich nach der Anzeige der Ergebnisse nach einer Nummer und einem Viewer fragt, um meinen nächsten Job zu automatisieren?“
Ich möchte beispielsweise, dass ich Folgendes eingebe:
> 2 evince
Das Skript wird evince
für das 2
2. Element des Suchergebnisses ausgeführt.dh, wenn es das ist, was ich im vorherigen Suchergebnis eingegeben habe, wird Folgendes ausgeführt:
evince /home/user/Dropbox/SharedWithFriends/math/classifications2010.pdf
Antwort1
Hier ist eine Variante Ihrer findme
Funktion, die die Ergebnisse abruft. Anstatt grep
sie jedoch zu nummerieren oder less
zu paginieren, listet sie sie aus einem internen Array auf und fordert Sie dann zur Auswahl Ihres Elements und Programms auf.
#!/usr/bin/env bash
readarray -O 1 -t results < <(locate -Abi '*\.'"$1" "$2" | grep --color=always -i "$2")
for((i=1; i <= ${#results[*]}; i++))
do
printf "%d: %s\n" $i "${results[i]}"
done
read -p "> " item program
$program "${results[item]}"
Ich habe Ihrem Originalskript einige Anführungszeichen hinzugefügt, um mit Leerzeichen in Dateinamen oder sogar Grep-Parametern besser umgehen zu können. Ich habe den readarray
Aufruf so angepasst, dass die Ergebnisse bei Index 1 statt 0 beginnen, sodass es der Nummerierung von Grep entspricht.
Antwort2
Beachten Sie, dass Ihr findme
Skript einige Probleme aufweist:
- Fehlende Anführungszeichen um Variablensubstitutionen
- Die Ausgabe von
grep --color=always
erzeugt Ergebnisse, die nicht in einer Befehlsersetzung verwendet werden können. Sie müssen sie durchgebenless
, aber versuchen Sie nicht, sie in einem Skript wiederzuverwenden. - grep und locate verwenden unterschiedliche Mustersyntaxen, daher
grep
funktioniert die Verwendung zum Färben des zweiten Arguments nicht immer. Die Übergabe-r
anlocate
bewirkt, dass reguläre Ausdrücke verwendet werden, allerdings mit einer Emacs-Syntax, die sich leicht von den von grep unterstützten Syntaxen unterscheidet.
In Bash können Sie verwendenmapfile
um einige Zeilen zuverlässig in ein Array zu packen. Kombinieren Sie es mitProzesssubstitutionum die Ausgabe eines Befehls zu verwenden. Drucken Sie dann dieses Array aus und lesen Sie die Eingabe des Benutzers.
findrun () {
mapfile search_hits <(locate -Abir ".*\.$1" "$2")
print '%s\n' "${search_hits[@]}" | grep --color=always -ine "$2"
if read -a cmd; then
set -- "${cmd[@]}"
set -- "$@" "${search_hits[$1]}"
shift
"$@"
fi
}
Eine alternative Schnittstelle wäre das Setzen der Positionsparameter. Das ist ein bisschen knifflig, weil man die Positionsparameter nicht von einer Funktion aus ändern kann, aber es gibt eineUmweg, es in Bash zu tunindem Sie ein Pseudonym verwenden und ein Skript als Quelle angeben. Vorsicht beim Zitieren.
alias findrun='. <(echo findrun_prepare \"\$@\"; echo set -- "\"\${search_hits[@]}\"")'
findrun_prepare () {
mapfile search_hits <(locate -Abir ".*\.$1" "$2")
print '%s\n' "${search_hits[@]}" | grep --color=always -ine "$2" >&2
}
Verwendung:
findrun pdf classifi
evince "$2"
Antwort3
Basierend auf der Lösung von Jeff Schaller. Ich habe eine Lösung gefunden und würde mich über Kommentare freuen, um sie zu verbessern.
#!/bin/bash
readarray -O 1 -t results < <(locate -Abi '*\.'"$1" "$2")
for((i=1; i <= ${#results[*]}; i++))
do
printf "%d: %s" $i "${results[i]}" | grep --color=always -i "$2"
done
read -p "> " item program
$program "${results[item]}"
Dies scheint eine einfache (bis auf die Komplexität der Themen) Antwort zu sein.
Aber es ist nicht gut genug, wenn die Ergebnisse mehr als eine bestimmte Zahl sind! In diesem Fall brauchen wir etwas wie more
oderless