2009-12-17 4 views

risposta

50

As Mark Rushakoff ha sottolineato, read -s sopprimerà l'eco dei caratteri digitati al prompt. Si può fare uso di tale caratteristica come parte di questo script per eco asterischi per ogni carattere digitato:

#!/bin/bash 
unset password 
prompt="Enter Password:" 
while IFS= read -p "$prompt" -r -s -n 1 char 
do 
    if [[ $char == $'\0' ]] 
    then 
     break 
    fi 
    prompt='*' 
    password+="$char" 
done 
echo 
echo "Done. Password=$password" 
+5

Devi 'disinserire IFS' o aggiungere' IFS = 'al tuo ciclo while altrimenti il ​​tuo ciclo si interromperà prematuramente sulle password che contengono spazi. Inoltre, dovresti aggiungere il flag '-r' a' read' in modo che le password possano contenere backslash. – SiegeX

+1

'password + =" $ char "' non ha funzionato sul mio sistema. Dovevo invece usare 'password =" $ {password} $ {char} "'. –

+2

@BradMace: non è necessario utilizzare Bash, ksh (93) o zsh oppure si sta utilizzando una versione molto vecchia di Bash (ad esempio, 2.05b). –

2
stty -echo 
read something 
stty echo 

interromperà l'immissione dell'utente sullo schermo per quella lettura. A seconda di cosa stai facendo con i prompt, potresti voler aggiungere un ulteriore comando echo per generare una nuova riga dopo la lettura.

5

Non so sulle stelle, ma stty -echo è tuo amico:

#!/bin/sh 
read -p "Username: " uname 
stty -echo 
read -p "Password: " passw; echo 
stty echo 

Fonte: http://www.peterbe.com/plog/passwords-with-bash

+0

Grazie! Funziona bene! –

+1

Questo sembra appena necessario dato che 'read' ha un'opzione' -s' (la domanda è taggata 'bash', quindi possiamo assumere caratteristiche bash-specifiche). Interrompere il comando 'read' (ad es. Digitando control-C) potrebbe lasciare il tty in modalità' -echo'. –

11

read -s dovrebbe mettere in modalità silenziosa:

-s  Silent mode. If input is coming from a terminal, characters are not echoed. 

See la sezione read in man bash.

+0

Vuole un feedback, non un silenzio noecho! – anthony

-1
#!/bin/bash 
echo "------------------------------" 

n=7 
echo " Enter Password :" 

for ((i=1;i<n;i++)) 
do 
    stty -echo 
    read -r -s -n 1 char 
    stty echo 

    echo -n "*" 
    pass+="$char" 

done 

echo " " 
echo " Your password : $pass " 

echo "" 
echo "-------------------------------" 
+0

Sono ben lungi dall'essere un esperto di bash, ma penso che questo codice abbia diversi problemi (come la password con una lunghezza fissa di 6 e non con i backspaces) – kratenko

5

Vorrei aggiungere qualcosa a soluzione Dennis Williamson s':

#!/bin/bash 

unset password 
echo -n "Enter password: " 
while IFS= read -p "$prompt" -r -s -n 1 char 
do 
    # Enter - accept password 
    if [[ $char == $'\0' ]] ; then 
     break 
    fi 
    # Backspace 
    if [[ $char == $'\177' ]] ; then 
     prompt=$'\b \b' 
     password="${password%?}" 
    else 
     prompt='*' 
     password+="$char" 
    fi 
done 

Nello script di esempio precedente gestisce correttamente il backspace.

Source

+0

Gestisce DEL "correttamente". Non fa nulla di speciale con backspace (Ctrl-H). –

+0

Gli utenti "_Normal_" utilizzano piuttosto il backspace standard, non Ctrl + H. Sopra lo script non gestisce correttamente anche i tasti freccia, ma ciao, è meglio gestire il backspace e _non_ gestire Ctrl + H, o non gestirli entrambi? ;) – Wirone

+1

Ctrl-H * è * backspace (lo standard Unicode lo chiama 'BACKSPACE'). '$ '\ 177'' è DEL (Unicode lo chiama' DELETE'). Alcuni programmi terminali possono opzionalmente mappare il tasto Backspace al carattere DEL, ma molti utenti "* normal *", incluso me stesso, lo associano al carattere backspace (Ctrl-H). Una soluzione robusta dovrebbe esaminare le impostazioni tty dell'utente. –

16

Mi è piaciuto molto la risposta che Wirone ha dato, ma non mi piace che la backspacing avrebbe continuato la rimozione di caratteri anche di nuovo nel "Enter password:" pronta.

Avevo anche alcuni problemi in cui premere troppo rapidamente i tasti causava la stampa di alcuni caratteri sullo schermo ... mai una cosa buona quando si richiede una password. =)

Quello che segue è la mia versione modificata di risposta Wirone s', che affronta questi temi:

#!/bin/bash 

unset PASSWORD 
unset CHARCOUNT 

echo -n "Enter password: " 

stty -echo 

CHARCOUNT=0 
while IFS= read -p "$PROMPT" -r -s -n 1 CHAR 
do 
    # Enter - accept password 
    if [[ $CHAR == $'\0' ]] ; then 
     break 
    fi 
    # Backspace 
    if [[ $CHAR == $'\177' ]] ; then 
     if [ $CHARCOUNT -gt 0 ] ; then 
      CHARCOUNT=$((CHARCOUNT-1)) 
      PROMPT=$'\b \b' 
      PASSWORD="${PASSWORD%?}" 
     else 
      PROMPT='' 
     fi 
    else 
     CHARCOUNT=$((CHARCOUNT+1)) 
     PROMPT='*' 
     PASSWORD+="$CHAR" 
    fi 
done 

stty echo 

echo $PASSWORD 
+0

Grazie per l'aggiornamento! – Wirone

+0

Una versione più avanzata è [ask_password_stars] (http://www.ict.griffith.edu.au/anthony/software/# ask_password_stars). È stato sviluppato come parte delle mie note personali su [Cryptogrphy, Password Input] (http://www.ict.griffith.edu.au/anthony/info/crypto/passwd_input.txt). – anthony

0

Se non si preoccupano che sia interattivo, si può semplicemente fare

read -s pass 
echo "$pass" | sed 's/./*/g' 

Questo mostrerà un * per ogni carattere della password inserita dopo aver premuto enter.

0

Ho appena fatto questa specifica funzione-Bash sulla base di Dennis Williamson 's, Wirone' s e risposte Logan VanCuren s':

ask() { 
    local 'args' 'char' 'charcount' 'prompt' 'reply' 'silent' 

    # Basic arguments parsing 
    while [[ "${1++}" ]]; do 
    case "${1}" in 
     ('--silent' | '-s') 
     silent='yes' 
     ;; 
     ('--') 
     args+=("${@:2}") 
     break 
     ;; 
     (*) 
     args+=("${1}") 
     ;; 
    esac 
    shift || break 
    done 

    if [[ "${silent}" == 'yes' ]]; then 
    for prompt in "${args[@]}"; do 
     charcount='0' 
     prompt="${prompt}: " 
     reply='' 
     while IFS='' read -n '1' -p "${prompt}" -r -s 'char'; do 
     case "${char}" in 
      # Handles NULL 
      ($'\000') 
      break 
      ;; 
      # Handles BACKSPACE and DELETE 
      ($'\010' | $'\177') 
      if ((charcount > 0)); then 
       prompt=$'\b \b' 
       reply="${reply%?}" 
       ((charcount--)) 
      else 
       prompt='' 
      fi 
      ;; 
      (*) 
      prompt='*' 
      reply+="${char}" 
      ((charcount++)) 
      ;; 
     esac 
     done 
     printf '\n' >&2 
     printf '%s\n' "${reply}" 
    done 
    else 
    for prompt in "${args[@]}"; do 
     IFS='' read -p "${prompt}: " -r 'reply' 
     printf '%s\n' "${reply}" 
    done 
    fi 
} 

Potrebbe essere usato come:

$ ask Username 
Username: AzureDiamond 
AzureDiamond 

$ ask -s Password 
Password: ******* 
hunter2 

$ ask First Second Third 
First: foo 
foo 
Second: bar 
bar 
Third: baz 
baz 
Problemi correlati