.bashrc 파일을 사용하여 bash에서 명령 출력을 읽으려고 합니다 while loop
.
while read -r line
do
echo "$line"
done <<< $(find . -type f)
내가 얻는 결과
ranveer@ranveer:~/tmp$ bash test.sh
./test.py ./test1.py ./out1 ./test.sh ./out ./out2 ./hello
ranveer@ranveer:~/tmp$
그 후 나는 시도했다
$(find . -type f) |
while read -r line
do
echo "$line"
done
하지만 오류가 발생했습니다 test.sh: line 5: ./test.py: Permission denied
.
그러면 현재 전체 줄을 한 번에 읽는다고 생각하기 때문에 한 줄씩 어떻게 읽습니까?
원하는 출력:
./test.py
./test1.py
./out1
./test.sh
./out
./out2
./hello
답변1
답변2
파이프를 사용하려는 경우 명령 대체가 필요하지 않습니다. 기본적 read
으로 읽기 stdin
이므로 입력을 파이프할 수 있습니다.
find . -type f -print0 |
while read -r -d '' line
do
echo "$line"
done
아니면 한 줄로
find . -type f -print0 | while read -r -d '' line; do echo "$line"; done
-print0
및 를 사용하면 -d ''
파일 이름에 새 줄이 생길 수 있으므로 기본적으로 줄 끝이 다음임을 의미합니다 read
( 및 를 사용하여 변경할 수 있음 -d
). ''
위에서 사용된 것은 실제로 널 바이트 bash
(와 동일 $'\0'
)입니다.
find
이미 언급한 또 다른 방법은 's 옵션을 사용하는 것입니다 -exec
. 이는 성능 측면에서 가장 좋은 옵션일 가능성이 높습니다( -exec cmd {} +
처리되는 모든 행에 대해 프로세스를 분기하지 않도록 변형을 사용하는 것을 기억하세요). 그러나 실제로는 while
루프 내에서 수행하는 작업과 처리 중인 데이터의 양 에 따라 달라집니다 . 귀하의 경우에는 그 차이가 무시할 수 있거나 허용될 수 있습니다.
답변3
파일 이름에 개행 문자가 포함되는 것을 방지할 수 있는 것은 없습니다. 각 파일에 대해 명령을 실행하는 정식 방법확립된예를 검색하여
find . -type f -exec cmd {} \;
Bash에서 작업을 수행하려면 다음을 수행하십시오.
find . -type f -exec bash -c '
for file do
something with "$file"
done' bash {} +
또한 스크립트에서 "읽기" 명령을 호출하는 정식 방법은 다음과 같습니다(입력에 대한 추가 처리를 원하지 않는 경우).
IFS= read -r var
-r
백슬래시 문자(구분 기호 및 줄 바꿈에 대한 이스케이프 문자)의 특수 처리를 중지하고 read
IFS=는 구분 기호 목록을 빈 문자열로 설정합니다 read
(그렇지 않으면 공백 문자가 목록에 있으면 입력 시작에서 제거됩니다). 그리고 끝).
셸에서 루프를 사용하는 것은 일반적으로 나쁜 생각입니다(수백 개의 2급 도구에 대해 하나 이상의 도구를 순차적으로 실행하는 대신 여러 도구를 사용하여 동시에 작업을 수행할 수 있는 셸에서 작업을 수행하는 방식이 아닙니다).
답변4
작은 수정Stefan Chazeras의 답변.
find . -type f -exec bash -c 'echo $0; head $0;' {} \;
이는 제공한 스크립트가 bash -c
첫 번째 매개변수를 사용하는 방법을 보여줍니다.