![Bash에서 폴더 식별](https://linux55.com/image/43762/Bash%EC%97%90%EC%84%9C%20%ED%8F%B4%EB%8D%94%20%EC%8B%9D%EB%B3%84.png)
기본 수준 폴더 내의 폴더만 식별하는 방법을 배우려고 합니다. 예:
- 기본
- -폴더 1
- -폴더 2
- -폴더 3
다음 스크립트로 시작합니다.
#!/bin/bash
LOCATION="/mnt/test/build/"
for folder in $(ls $LOCATION); do
echo "$folder"
done
그러나 스크립트를 실행하면 전체 내용이 에코되고 폴더 내에 공백이 있으면 두 줄에 이름이 추가됩니다. 에코 라인을 에서 "$folder"
로 변경하면 '$folder'
해당 폴더만 에코됩니다. 암시적인 기사도 좋습니다.
답변1
ls
단순히 디렉토리의 내용을 반복하는 대신 글로빙을 사용하십시오 .
#!/bin/bash
LOCATION="/mnt/test/build/"
for folder in "$LOCATION"/*; do
[ -d "$folder" ] || continue
echo "$folder"
done
이 [ -d "$folder" ]
명령은 $folder
디렉터리인지 여부를 테스트합니다. 그렇지 않은 경우 해당 항목을 건너뜁니다 continue
. $LOCATION
및 주변의 따옴표에 유의하세요 $folder
. 공백이 포함된 경우 스크립트가 $LOCATION
중단되는 것을 방지합니다.
정말로 처리할 것이 필요한 경우 ls
다음과 같이 사용하십시오.
ls "$LOCATION" | while read folder; do
echo "$folder"
done
루프 이후 루프 내부의 변수에 액세스해야 한다는 추가적인 제한이 있는 경우 Bash 프로세스 대체를 사용하십시오.
while read folder; do
echo "$folder"
done < <(ls "$LOCATION")
Bash 매뉴얼은 다음 위치에 있습니다.http://www.gnu.org/software/bash/manual/.
답변2
출력을 구문 분석하지 않습니다.ls
. ls
디렉토리의 내용을 나열할 필요는 없습니다 . 쉘 와일드카드를 사용할 수 있습니다.
을 작성하면 $(ls $LOCATION)
명령의 출력은 ls
공백이 포함된 별도의 단어로 분할됩니다. 이것이 바로 귀하의 명령이 파일 이름을 공백으로 뒤섞은 이유입니다. 공백이 구분 기호로 표시되지 않도록 해당 변수를 수정할 수 있지만 IFS
파일 이름을 구분하는 데 사용되는 줄 바꿈과 파일 이름 내의 줄 바꿈을 구별할 수 있는 방법이 없으므로 문제를 완전히 피할 수는 없습니다. 또한 분할로 인해 생성된 각 단어는 glob(즉, 와일드카드 패턴)으로 처리되고 일치하는 파일 목록(있는 경우)으로 대체됩니다. 쉘 스크립팅의 간단한 규칙은 다음과 같습니다."$foo"
변수 대체 및 명령 대체에는 항상 큰따옴표를 사용하세요."$(foo)"
. 큰따옴표는 분할과 와일드카드를 방지합니다.
다음 코드 조각은 파일 이름을 변경하지 않고 각 파일의 전체 경로를 인쇄한다는 점을 제외하면 루프와 동일합니다.
for x in "$LOCATION"/*; do
echo "$x"
done
상대 경로를 원하는 경우 $LOCATION
한 가지 방법은 먼저 대상 디렉터리로 변경하는 것입니다.
cd "$LOCATION"
for x in *; do
echo "$x"
done
또 다른 방법은 파일 이름에서 접두사를 제거하는 것입니다.
for full_path in "$LOCATION"/*; do
relative_name=${full_path#"$LOCATION/"}
echo "$relative_name"
done
그러면 대상 디렉터리에 있는 모든 파일의 이름이 인쇄됩니다. 하위 디렉터리(디렉토리에 대한 심볼릭 링크 포함)만 나열하려면 /
glob 패턴에 를 추가하여 일치 항목을 제한하세요.
for full_path in "$LOCATION"/*/; do
relative_name=${full_path#"$LOCATION/"}
relative_name=${relative_name%/}
echo "$relative_name"
done
심볼릭 링크를 포함하지 않으려면 루프 내부의 디렉터리에 대해 명시적인 테스트를 수행하세요.
for full_path in "$LOCATION"/*/; do
if ! [ -d "$full_path" ]; then continue; fi
relative_name=${full_path#"$LOCATION/"}
relative_name=${relative_name%/}
echo "$relative_name"
done
답변3
귀하의 레벨 아래에 있는 모든 디렉토리를 찾으십시오.
find . -type d
자신을 한 수준으로 제한하고 싶다면
find . -type d -maxdepth 1 -mindepth 1
편집하다
귀하의 질문 중 일부를 놓쳤습니다.
SAVEIFS=$IFS
IFS=$(echo -en "\n\b")
for dir in $( find . -type d -maxdepth 1 -mindepth 1 ) ; do
echo ${dir}
done
IFS=$SAVEIFS
그러나 수행하려는 작업에 따라 -exec
find 옵션을 사용하여 각 파일에 대해 명령을 실행할 수도 있습니다.
답변4
이 명령은 $LOCATION에서 직접 모든 디렉터리만 찾습니다. 해당 디렉토리의 내용은 나열되지 않습니다.
#!/bin/bash
LOCATION="/mnt/test/build/"
find "$LOCATION" -mindepth 1 -maxdepth 1 -type d
절대 경로 대신 상대 경로만 인쇄하려면 다음 명령을 사용하십시오.
find "$LOCATION" -mindepth 1 -maxdepth 1 -type d -printf "%f\n"