2015-07-09 7 views
7

Sono interessato a digitare una parola chiave di ricerca nel terminale e in grado di vedere l'output immediately e interactively. Ciò significa, come cercare in google, voglio ottenere risultati immediatamente dopo ogni carattere o parola inserita.Come ottenere il tipo AJAX (interattivo) di RICERCA in LINUX per trovare i file?

Ho pensato di farlo combinando il comando WATCH e il comando FIND ma non in grado di portare gli interattivi.

lascia supporre, per cercare un file con il nome 'suggerimento' nel nome del file, io uso il comando

$ find | grep -i hint 

questo praticamente mi dà i risultati di output discreti.

Ma quello che voglio è lo stesso comportamento in modo interattivo, che significa senza ridigitare il comando ma digitando solo la STRINGA DI RICERCA.

Ho pensato di scrivere uno script di shell che legge da uno STDIN ed esegue il PIPED-COMMAND sopra per ogni 1 sec. Quindi, qualunque cosa scriva, lo prendo come un'istruzione ogni volta per il comando. Ma il comando WATCH non è interattivo.

Sono interessato a sorta di seguito di USCITA:

$ hi 
./hi 
./hindi 
./hint 

$ hint 
./hint 

Se qualcuno mi può aiutare con un modo migliore alternativa al posto del mio codice pseudo, che è anche bello

+0

È necessario accettare i backspaces? – 123

+0

Sì, invece di premere il tasto INVIO, semplicemente digitando o correggendo per backspace. Il programma deve elencare i file secondo i caratteri correnti (di quel secondo) (in quella stringa). –

risposta

2

siamo imbattuti aross questa vecchia domanda, trovato interessante e ho pensato di fare un tentativo. Questo script BASH ha funzionato per me:

#!/bin/bash 
# Set MINLEN to the minimum number of characters needed to start the  
# search. 
MINLEN=2 
clear 
echo "Start typing (minimum $MINLEN characters)..." 
# get one character without need for return 
while read -n 1 -s i 
do 
    # get ascii value of character to detect backspace 
    n=`echo -n $i|od -i -An|tr -d " "` 
    if (($n == 127)) # if character is a backspace... 
    then 
     if ((${#in} > 0)) # ...and search string is not empty 
     then 
      in=${in:0:${#in}-1} # shorten search string by one 
      # could use ${in:0:-1} for bash >= 4.2 
     fi 
    elif (($n == 27)) # if character is an escape... 
    then 
     exit 0 # ...then quit 
    else # if any other char was typed... 
     in=$in$i # add it to the search string 
    fi 
    clear 
    echo "Search: \""$in"\"" # show search string on top of screen 
    if ((${#in} >= $MINLEN)) # if search string is long enough... 
    then  
     find "[email protected]" -iname "*$in*" # ...call find, pass it any parameters given 
    fi 
done 

Spero che questo faccia ciò che intendete (ed) fare. Ho incluso un'opzione "start dir", perché le inserzioni possono diventare abbastanza ingombranti se si cerca attraverso un'intera cartella home o qualcosa del genere. Basta scaricare il $1 se non ne hai bisogno. Utilizzando il valore ascii in $n dovrebbe essere facilmente possibile includere alcune funzionalità hotkey come chiudere o salvare i risultati.

EDIT:

Se si avvia lo script verrà visualizzato "iniziare a digitare ..." e attendere tasti da premere. Se la stringa di ricerca è sufficientemente lunga (come definito dalla variabile MINLEN), la pressione di un tasto attiverà l'esecuzione di find con la stringa di ricerca corrente (il numero grep sembra essere ridondante qui). Lo script passa tutti i parametri dati a find. Ciò consente migliori risultati di ricerca e elenchi di risultati più brevi. -type d per esempio limiterà la ricerca alle directory, -xdev manterrà la ricerca sul file system corrente ecc. (Vedere man find). I backspaces accorciano la stringa di ricerca di uno, mentre premendo Escape si esce dallo script. La stringa di ricerca corrente viene visualizzata in alto. Ho usato -iname per la ricerca senza distinzione tra maiuscole e minuscole. Cambialo in `-name 'per ottenere il comportamento case-sensitive.

+0

Grazie per lo script pulito. È possibile vedere la stringa di ricerca anche quando digito? E ho scoperto che esce dallo script quando uso backspace con il messaggio di errore "espressione di sottostringa <0". E, per favore, menziona anche l'uso, nel modo in cui avevi intenzione di usarlo dando un esempio dettagliato modificando la risposta. Sarebbe un buon valore aggiunto alla tua risposta. –

+0

Per qualche motivo la mia versione di bash non ha dato quel messaggio di errore. L'accorciamento dell'accorciamento delle stringhe in un 'if/then' dovrebbe risolverlo comunque. –

+0

Eccellente. Sta benissimo ora. Ma sto ancora ricevendo quell'errore se uso backspace. La mia versione di bash è '4.1.2 (1) -release' –

1

Questo codice di seguito accetta l'input su stdin, un metodo di filtro come macro in "$1" e le uscite passano a stdout.

Puoi usarlo per es., Come segue: macro filtraggio

#Produce basic output, dynamically filter it in the terminal, 
#and output the final, confirmed results to stdout 
vi `find . | terminalFilter` 

Il valore predefinito è grep -F "$pattern" lo script fornisce la variabile di modello, come tutto ciò che è attualmente inserito. I risultati immediati in funzione di ciò che è attualmente inserito vengono visualizzati sul terminale . Quando si preme <Enter>, i risultati diventano definitivi e vengono emessi a stdout.

#!/usr/bin/env bash 

##terminalFilter 

del=`printf "\x7f"` #backspace character 

input="`cat`"  #create initial set from all input 
#take the filter macro from the first argument or use 
# 'grep -F "$pattern"' 
filter=${1:-'grep -F "$pattern"'} 
pattern= #what's inputted by the keyboard at any given time 

printSelected(){ 
    echo "$input" | eval "$filter" 
} 
printScreen(){ 
    clear 
    printSelected 
    #Print search pattern at the bottom of the screen 
    tput cup $(tput lines); echo -n "PATTERN: $pattern" 
} >/dev/tty 
#^only the confirmed results go `stdout`, this goes to the terminal only 

printScreen 
#read from the terminal as `cat` has already consumed the `stdin` 
exec 0</dev/tty 
while IFS=$'\n' read -s -n1 key; do 
    case "$key" in 
    "$del") pattern="${pattern%?}";; #backspace deletes the last character 
     "") break;; #enter breaks the loop 
     *) pattern="$pattern$key";; #everything else gets appended 
            #to the pattern string 
    esac 
    printScreen 
done 

clear 
printSelected 
+0

Grazie per la risposta. Ma ho provato a usarlo, non ha funzionato. Puoi aggiornare l'utilizzo? lo script è interattivo? In realtà la risposta di cui sopra ha risolto il problema. Ma vorrebbe conoscere anche il tuo approccio. –

+0

Grazie per averci provato. Che senso ha che non funziona? Questo dovrebbe essere un approccio più universale - come se non fosse hardcode 'find', ma tu fornisci l'output find su stdin, e può essere ulteriormente convogliato in un altro comando. – PSkocik

+0

Se si salva lo script come 'terminalFilter', si esegue' chmod + x terminalFilter' e quindi 'find | ./terminalFilter', dovresti ottenere risultati di ricerca filtrati in modo interattivo e dovresti essere in grado di riutilizzare facilmente l'output filtrato. – PSkocik

Problemi correlati