스크립트는 다음과 같습니다
#!/bin/bash
IFS="
"
command="ls /tmp"
for file in `$command`;
do
echo $file
done
출력은 다음과 같습니다
$ ./test.sh
./test.sh: line 17: ls /tmp: No such file or directory
답변1
문제는 공백이 포함된 변수를 $IFS
개행 문자로 설정했기 때문에 bash가 변수에 대해 올바르게 수행하지 않는다는 것입니다. 이로 인해 첫 번째 단어를 명령으로 전달하고 나머지 단어를 인수로 전달하는 대신 전체를 하나의 명령으로 실행하려고 합니다.
strace
다음이 표시되는 대신 이 명령을 실행하려는 경우 :
execve("/bin/ls", ["ls", "/tmp"], [/* 42 vars */]) = 0
--- -----
| |-------------> 2nd argument
|---------------------> 1st argument, the command to run.
ls /tmp
첫 번째 매개변수가 단독 이 아니라는 것을 알 수 있는데 ls
, 이는 시스템이 할 수 없는 일입니다.
변수를 설정하지 않으면 스크립트가 실제로 예상한 대로 작동합니다 IFS
. 그러나 실제로 ls
는 iterate 명령의 출력을 사용해서는 안 됩니다 .알다출력에는 공백이나 기타 이상한 문자가 포함되지 않습니다. 표시하려면:
$ touch 'file name with spaces'
$ for i in $(ls ./); do echo "$i"; done
file
name
with
spaces
올바른 방법은 다음 중 하나를 사용하는 것입니다.
$ for i in *; do echo "i is: $i"; done
i is: file name with spaces
$ find . -type f | while IFS= read -r i; do echo "i is: $i"; done
i is: ./file name with spaces
정말로 사용하고 싶다면 ls
최소한 while 루프와 함께 사용하세요. 여러 가지 이유로 여전히 작동하지 않지만 적어도 공백을 처리할 수는 있습니다.
$ ls | while read i; do echo "i is: $i"; done
i is: file name with spaces
마지막으로, 대처할 수 있는어느개행, 백슬래시, 공백 등이 포함된 파일 이름. 사용:
$ find . -type f -print0 | while IFS= read -r -d '' i; do echo "i is: $i"; done
i is: ./file name with spaces
답변2
이 IFS
부분을 제거하세요.
$IFS
예, 내부 필드 구분 변수입니다 bash
. 스크립트에 추가한 행으로 인해 bash
필드가 기본값(공백, 탭 및 줄바꿈)이 아닌 줄바꿈으로만 구분됩니다. ls
탭으로 구분된 출력을 제공합니다.
이것은 작동합니다:
#!/bin/bash
command="ls /tmp"
for file in `$command`;
do
echo $file
done