스크립트에서 출력이 리디렉션되었습니다.
$ ls -ltr |awk '{print $9}'
default.txt
dfah.txt
fruit.txt
fruit_prices.txt
dfh.txt
header.txt
testfile.txt
topoutput.txt
쉘에 작성된 스크립트:
while read line
do
var=`sed -e 's/\.txt/txt\.txt/' $line`
echo $var
done < `ls -ltr |awk '{print $9}'`
에러 발생됨:
-bash: `ls -ltr |awk '{print $9}'`: ambiguous redirect
위 코드에서 모호한 리디렉션이 어떻게 발생하는지 전문가의 도움을 받을 수 있습니까?
답변1
노력하다
ls -ltr |awk '{print $9}' | while read line
do
var=`sed -e 's/\.txt/txt\.txt/' $line`
echo $var
done
이 명령을 내렸습니다.
while read line ; do
...
done < a b c d
구문 분석할 수 없음
답변2
하려고 하는 것 같군요
while read line
do
...
done < <(ls -ltr | awk '{print $9}')
그런데 왜? (while read line
아케마의 대답)가 더 명확하고 이식성이 뛰어납니다.
좋습니다. 답변을 더욱 완전하게 만들려면 다음을 수행하세요.졸탄 뵈스조르메니(Zoltán Böszörményi)는 다음과 같이 지적합니다.,
ls -ltr | awk '{print $9}' | while read line
do
...
done
Bash(및 기타 일부 셸)에서는 주체가 subshell 에서 실행되므로 while
셸 상태(예: 셸 변수)에 대한 상태 변경이 루프 외부에서 지속되지 않습니다. 이에 대해서는 다음 장소에서 더 자세히 논의됩니다.
- Bash에서
read
파이프가 값을 설정하지 않은 후, - 내 변수가
while read
한 루프에서는 로컬이지만 겉보기에 유사한 다른 루프에서는 로컬이 아닌 이유는 무엇입니까? - BashFAQ/024: 파이프라인 내의 루프에 변수를 설정하고 있습니다. 루프가 끝나면 왜 사라지나요? 아니면 왜 데이터를 으로 전송할 수 없나요
read
? - 그리고여기, 여기 그리고 여기 스택 오버플로에.
< <(…)
이 답변 상단의 코드는 문제를 피하는 한 가지 방법입니다.
하지만 또 다른 것
당신은하고 있습니다 ls -ltr | awk '{print $9}'
. 이는 수정된 날짜/시간 순으로 파일을 나열한 다음 파일 이름을 추출하는 패치워크처럼 보입니다. 몇 가지 질문이 있습니다:
- 공백이 포함된 파일 이름의 경우 이 작업이 실패합니다.
ls
생성하라고 하면 스스로 추가 작업을 수행하는 것입니다.나정보(파일 모드, 소유자, 크기 등)를 나열한 다음 처음에 생성할 필요가 없으면 제거합니다.
생략하면 두 가지 문제를 모두 해결할 수 있습니다.l
옵션 ls
및 생략 awk
:
while read line
do
...
done < <(ls -tr)
공백으로 시작하거나 끝나는 파일 이름은 여전히 문제를 일으킬 수 있습니다.
당신은 또한 볼 수 있습니다ls(1)의 출력을 분석하면 안되는 이유.
답변3
"cat file | while read line ..."은 서브쉘에서 "while"의 본문을 실행하기 때문에 쉘 변수는 서브쉘 외부에 표시되지 않지만 "while read line ; do ... ; did < <(command )"를 사용하여 동일한 쉘에서 실행합니다.
이것은 내 테스트 파일입니다.
$ cat fruits.txt
apple
cherry
pear
plum
두 스크립트와 결과의 차이점을 살펴보세요.
$ cat a.sh
#!/bin/bash
FOUND=0
while read fruit ; do
case $fruit in
cherry)
echo yay, cherry found
FOUND=1
;;
esac
done < <(cat fruits.txt)
echo cherry found: $FOUND
$ ./a.sh
yay, cherry found
cherry found: 1
하지만
$ cat b.sh
#!/bin/bash
FOUND=0
cat fruits.txt | while read fruit ; do
case $fruit in
cherry)
echo yay, cherry found
FOUND=1
;;
esac
done
echo cherry found: $FOUND
$ ./b.sh
yay, cherry found
cherry found: 0
답변4
다음과 같이 할 수도 있습니다.
while read line; do
var=`echo "$line" |sed -e 's/\.txt/txt\.txt/'`
echo $var
done <<_EOT_
$(ls -ltr | awk '{print $9}')
_EOT_