Le script Bash ne lit pas l'entrée

8

J'ai un script qui est supposé exécuter une commande en arrière-plan, et il le fait. Le problème est que lorsque le script rencontre une commande de lecture, il n'interrompt pas et n'accepte pas d'entrée. C'est ici:

printf "Where is yo music?: "
read musicPath

cd $musicPath
ls | while read currentSong;do
  seconds=`mdls "$currentSong"|sed -n '20p'|awk '{print $3}'|cut -d. -f1`
  hours=$((seconds / 3600))
  seconds=$((seconds % 3600))
  minutes=$((seconds / 60))
  seconds=$((seconds % 60))
  echo "Song: $currentSong"
  echo "Length: $hours:$minutes:$seconds"
  afplay "$currentSong"&
  printf "yes (y), no (n), or maybe (m): "
  read choice
  case $choice in
    y)
      mkdir ../Yes
      mv "$currentSong" ../Yes
    ;;
    n)
      mkdir ../No
      mv "$currentSong" ../No
    ;;
    m)
      mkdir ../Maybe
      mv "$currentSong" ../
    ;;
    *)
      echo "Invalid option! Continuing..."
    ;;
  esac
  kill $!
done
Cade
la source
en bash, vous pouvez fournir l'invite dans la commande read elle-même:read -p "where is yo music? " musicPath
glenn jackman

Réponses:

16

Il y a de nombreux problèmes avec ce script, mais celui qui cause votre problème spécifique est parce que vous lisez à partir d'un canal (la sortie de ls).

1. Ne pas analyserls

Utilisez-le à la place

for currentSong in *; do
  ...
done

Mis à part les nombreuses raisons que vous ne devriez pas analyser ls, le problème que vous voyez est que STDIN est connecté à la sortie de ls. Ainsi, lorsque vous readémettez un , il ne peut pas lire depuis le terminal car STDIN n'est pas connecté au terminal.


2. Utilisez plus de citations

Vous avez un bon nombre de citations réparties, mais vous en manquez encore. Surtout juste sur le cd.

cd "$musicPath"

aussi

case "$choice"


3. N'utilisez pas de backticks

L'utilisation de backticks est parfois acceptable. Je les utilise fréquemment sur la ligne de commande car il est plus rapide à taper que $(). Mais pour les scripts, il est préférable d'utiliser à la $()place.

seconds="$(mdls "$currentSong"|sed -n '20p'|awk '{print $3}'|cut -d. -f1)"


4. mkdir

Votre mkdirgénérera une erreur (inoffensive mais bruyante) si les répertoires existent déjà. Ajoutez- -py un qui fera mkdirque rien ne fonctionnera silencieusement s'il existe déjà

mkdir -p ../Yes


Oui, il y a beaucoup d'écueils avec bash. Ne pas essayer d'être dur, juste essayer de briser les mauvaises habitudes.
S'amuser :-)

Patrick
la source
Merci pour tous les conseils! J'adore ce truc, donc pas de soucis. J'adore toujours apprendre de nouvelles choses (:
Cade