Bashスクリプトが入力を読み取らない


8

コマンドをバックグラウンドで実行することを想定したスクリプトがあります。問題は、スクリプトが読み取りコマンドに遭遇したときに、一時停止して入力を受け付けないことです。ここにあります:

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

bashで、あなたがリードコマンド自体にプロンプトを提供することができます:read -p "where is yo music? " musicPath
グレンはジャックマン

回答:


16

このスクリプトには多くの問題がありますが、特定の問題を引き起こしているのは、パイプ(の出力ls)から読み取っていることが原因です。

1. 解析しないls

代わりにこれを使用してください

for currentSong in *; do
  ...
done

解析してlsはならない多くの理由は別として、STDINがの出力に接続されていることが原因で問題が発生していますls。したがって、readSTDINが端末に接続されていないため、を発行すると、端末から読み取ることができません。


2. 引用符を増やす

かなりの量の見積りが広がっていますが、それでもいくつか不足しています。主にだけでcd

cd "$musicPath"

また

case "$choice"


3. バックティックを使用しない

時々バッククォートの使用は問題ありません。コマンドラインでは、を入力するよりも速く入力できるため、頻繁に使用します$()。ただし、スクリプトの場合は、$()代わりに使用することをお勧めします。

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


4. mkdir

あなたは、mkdirディレクトリがすでに存在する場合(無害しかし、うるさい)エラーが発生します。そこに-pin を追加すると、mkdirすでに存在する場合は何も表示されずに何も行われません。

mkdir -p ../Yes


はい、bashには多くの落とし穴があります。過酷なことをしようとするのではなく、悪い習慣を打破しようとするだけです。
楽しんで :-)


すべてのヒントをありがとう!私はこれが大好きなので心配する必要はありません。常に新しいことを学ぶのが大好き(:
Cade
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.