Bash 스크립트가 입력을 읽지 못합니다

Bash 스크립트가 입력을 읽지 못합니다

백그라운드에서 명령을 실행하는 스크립트가 있는데 정확히 그 일을 합니다. 문제는 스크립트가 읽기 명령을 만나면 일시 중지하고 입력을 받아들이지 않는다는 것입니다. 여기있어:

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

답변1

이 스크립트에는 많은 문제가 있지만 특정 문제를 일으키는 원인은 ls파이프(의 출력)에서 데이터를 읽기 때문입니다.

1.파싱되지 않음ls

대신 이것을 사용하십시오

for currentSong in *; do
  ...
done

구문 분석을 하지 말아야 하는 많은 이유 중에서 ls여러분이 보고 있는 문제는 STDIN이 출력에 연결되어 있기 때문입니다 ls. 따라서 를 실행하면 readSTDIN이 터미널에 연결되어 있지 않기 때문에 터미널에서 읽을 수 없습니다.


2.더 많은 인용문 사용

꽤 많은 인용문이 있지만 여전히 몇 가지가 누락되어 있습니다. 주로 cd.

cd "$musicPath"

반품

case "$choice"


삼.백틱을 사용하지 마세요

때로는 백틱을 사용해도 괜찮습니다. . 보다 낫기 때문에 명령줄에서 자주 사용합니다 $(). 하지만 스크립팅에는 사용하는 $()것이 더 좋습니다.

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


4. 목차

mkdir디렉토리가 이미 존재하는 경우 (해롭지는 않지만 시끄러운) 오류가 생성됩니다. -p거기에 하나를 추가하십시오 mkdir. 이미 존재하는 경우 자동으로 아무 작업도 수행되지 않습니다.

mkdir -p ../Yes


예, bash에는 많은 문제가 있습니다. 가혹하게 굴려고 노력하는 것이 아니라 단지 나쁜 습관을 고치려고 노력하는 것뿐입니다.
재미있게 보내세요 :-)

관련 정보