아래 함수를 사용하여 모든 하위 디렉터리를 인쇄하려고 하는데 어떤 이유로 파일 이름에 공백("")이 포함되어 있으면 echo
이름이 두 부분으로 분할됩니다. 예는 다음과 같습니다.
내 디렉터리에는 이라는 디렉터리가 포함되어 있습니다 r1 August.request
.
출력은 다음과 같습니다
r1
August.request
내가 찾고 있어요
r1 August.request
이것은 내 스크립트입니다.
#!/bin/bash
function ScanFile {
for file in `ls` ; do
if [[ -d "$file" ]] ; then
cd "$file"
ScanFile
cd ..
else
echo "$file"
fi
done
}
ScanFile
답변1
SH 호환 쉘에는 소위 IFS 변수가 있습니다. IFS 대표내부 필드 구분 기호. 이 변수는 쉘이 매개변수 경계(예: 위치 매개변수의 경계)를 감지하는 방법을 제어합니다.
기본적으로는 다음과 같습니다.
set IFS=$' \t\n'
이는 입력을 공백, 탭 및 줄 바꿈으로 구분된 토큰으로 분할한다는 것을 의미합니다.
파일은 공백으로 구성되어 있습니다. 이 시도:
OLD_IF="$IFS"
IFS=$'\t\n'
for file in `ls -1` ; do
# Content of your loop
done
IFS="$OLD_IFS"
여기서 중요한 점은 이전 IFS 값을 저장하고 복원하는 것입니다.
편집: ls -1
한 줄에 하나의 파일 목록을 추가하여 언급한 작업을 수행합니다.
답변2
배쉬에서:
shopt -s globstar
ls -1d **/
답변3
함수 구문 분석의 따옴표가 없는 출력입니다 ls
. 이는 쉘이 ls
.
대신에:
dirwalk () {
indent=${1:-0}
for name in *; do
[ ! -e "$name" ] && continue
if [ -d "$name" ]; then
printf '%*sDir: "%s"\n' "$indent" "" "$name"
( cd "$name" && dirwalk "$(( indent + 4 ))" )
else
printf '%*sFile: "%s"\n' "$indent" "" "$name"
fi
done
}
또는 화려한 들여쓰기 없이
dirwalk () {
for name in *; do
[ ! -e "$name" ] && continue
if [ -d "$name" ]; then
printf 'Dir: "%s"\n' "$name"
( cd "$name" && dirwalk )
else
printf 'File: "%s"\n' "$name"
fi
done
}
*
대신 의 출력을 사용하면 ls
파일 이름에 공백이 포함된 경우에도 현재 디렉터리를 반복하기 위해 올바르게 구분된 파일 이름 목록을 생성합니다.
테스트는 -e
반복하는 항목이 실제로 존재하는지 확인하는 것입니다. 빈 디렉토리를 입력하면 *
확장되지 않고 그대로 유지됩니다 *
. 에서 일치하지 않는 패턴이 비어 있도록 셸 옵션을 bash
설정할 수 있습니다 .nullglob
shopt -s nullglob
서브셸(괄호 안에)에서 이를 사용하면 이전 디렉터리로 돌아가는 것을 cd
기억할 필요가 없습니다 . cd ..
외부 환경은 내부 환경에 영향을 받지 ( ... )
않습니다 .cd
printf
대신 사용하면 echo
출력 형식을 더 잘 제어할 수 있습니다. 또한보십시오 "왜 printf가 echo보다 나은가요?".