È possibile in una bash interattiva shell per immettere un comando che restituisca del testo in modo che appaia al prompt dei comandi successivo, come se l'utente avesse digitato quel testo in quel prompt?
Voglio essere in grado di source
uno script che genererà una riga di comando e la emetterà in modo che appaia quando il prompt ritorna al termine dello script in modo che l'utente possa opzionalmente modificarlo prima di premere enter
per eseguirlo.
Questo può essere ottenuto con xdotool
ma funziona solo quando il terminale è in una finestra X e solo se è installato.
[[email protected]] 100 $ xdotool type "ls -l"
[[email protected]] 101 $ ls -l <--- cursor appears here!
È possibile farlo solo utilizzando bash?
Risposta accettata:
Con zsh
, puoi usare print -z
per inserire del testo nel buffer dell'editor di riga per il prompt successivo:
print -z echo test
adescare l'editor di riga con echo test
che puoi modificare alla richiesta successiva.
Non credo bash
ha una caratteristica simile, tuttavia su molti sistemi è possibile adescare il buffer di input del dispositivo terminale con il TIOCSTI
ioctl()
:
perl -e 'require "sys/ioctl.ph"; ioctl(STDIN, &TIOCSTI, $_)
for split "", join " ", @ARGV' echo test
Inserisce echo test
nel buffer di input del dispositivo terminale, come se fosse ricevuto dal terminale.
Una variazione più portabile della Terminology
di @mike approccio e ciò non sacrifica la sicurezza sarebbe inviare all'emulatore di terminale un query status report
abbastanza standard sequenza di escape:<ESC>[5n
quali terminali rispondono invariabilmente (quindi come input) come <ESC>[0n
e associalo alla stringa che vuoi inserire:
bind '"e[0n": "echo test"'; printf 'e[5n'
Se all'interno dello screen
di GNU , puoi anche fare:
screen -X stuff 'echo test'
Ora, ad eccezione dell'approccio ioctl TIOCSTI, chiediamo all'emulatore di terminale di inviarci una stringa come se fosse digitata. Se quella stringa viene prima di readline
(bash
's line editor) ha disabilitato l'eco locale del terminale, quindi quella stringa verrà visualizzata non al prompt della shell, incasinando leggermente il display.
Per ovviare a questo problema, puoi ritardare leggermente l'invio della richiesta al terminale per assicurarti che la risposta arrivi quando l'eco è stato disabilitato da readline.
bind '"e[0n": "echo test"'; ((sleep 0.05; printf 'e[5n') &)
(qui assumendo il tuo sleep
supporta una risoluzione inferiore al secondo).
Idealmente vorresti fare qualcosa come:
bind '"e[0n": "echo test"'
stty -echo
printf 'e[5n'
wait-until-the-response-arrives
stty echo
Tuttavia bash
(contrariamente a zsh
) non supporta tale wait-until-the-response-arrives
che non legge la risposta.
Tuttavia ha un has-the-response-arrived-yet
funzione con read -t0
:
bind '"e[0n": "echo test"'
saved_settings=$(stty -g)
stty -echo -icanon min 1 time 0
printf 'e[5n'
until read -t0; do
sleep 0.02
done
stty "$saved_settings"
Ulteriori letture
Vedi la risposta di @starfry che espande le due soluzioni fornite da @mikeserv e da me con alcune informazioni più dettagliate.