디렉터리와 하위 디렉터리의 모든 파일을 나열하고 배열에 저장한 다음 몇 가지 작업을 수행해야 합니다(기본적으로 배열에 대한 for 루프 및 속성 설정).
나는 다음과 같이 시작했습니다:
var=$(find ./ -type f)
내 문제는 파일 이름에 공백과 기타 친숙하지 않은 문자(내 잘못이 아닙니다!)가 포함되어 있어 문자열 배열(예: find 명령의 출력)을 구문 분석하는 것이 매우 복잡하다는 것입니다.
그래서 나는 내가 사용할 수 있다는 것을 알았습니다.찾기-print0재귀적이지 않은 것(하위 디렉터리가 아닌 디렉터리만)으로 나타나는 것을 제외하면 잘 작동합니다.
재귀적으로 보기 위해 전달할 수 있는 매개변수나 이에 상응하는 명령이 있습니까?
- 디렉터리 및 하위 디렉터리의 모든 파일 나열
- 목록을 문자열 배열로 저장하시겠습니까?
답변1
find
항상 재귀적이지만 귀하의 것입니다.
var=$(find ./ -type f)
는스칼라배열 변수 할당이 아닌 변수 할당입니다. $var
마지막으로 문자열을 포함합니다: find
개행 문자²를 포함한 전체 출력
bash 복사 zsh 구문에서 배열 변수 할당은 다음과 같습니다.
var=( 'first element' second-element etc... )
각 파일의 출력을 얻으려면 출력을 NUL 문자로 find -print0
분할해야 합니다 . zsh에서는 매개변수 확장 플래그를 find
사용할 수 있습니다 .0
var=( ${(0)"$(find . -type f -print0)"} )
Bash에는 이에 상응하는 것이 없으며 일반적으로 데이터 구조에 NUL을 저장할 수 없습니다. 그러나 버전 4.4부터 readarray
프로세스 대체와 함께 내장 기능을 사용할 수 있습니다.
readarray -td '' var < <(find . -type f -print0)
readarray
find
각 레코드를 입력(여기서는 프로세스 대체를 통해 생성된 파이프)에 별도의 요소로 저장합니다. 를 사용하면 -d ''
레코드 구분 기호는 개행 대신 NUL입니다. 사용하면 -t
레코드 구분 기호가 제거됩니다. bash는 어쨌든 변수에 NUL을 저장할 수 없기 때문에 현재 버전의 bash에서는 필요하지 않지만 미래를 위해 추가했습니다.
요소를 반복하려면 다음을 수행하십시오.
for file in "${var[@]}"; do
something with "$file"
done
여기서는 배열 사용을 건너뛰고 find
with의 출력에서 직접 루프할 수도 있습니다.
while IFS= read -rd '' -u3 file; do
something with "$file"
done 3< <(find . -type f -print0)
당신은 또한 볼 수 있습니다찾기 결과를 반복하는 것이 왜 나쁜 습관입니까?find
일반적으로 발견되는 파일을 올바르게 루프하는 방법을 알아보세요.
-prune
¹ 특정 디렉토리를 사용하거나 입력하지 말라고 명시적으로 지시하지 않거나 -xdev
일부 find
구현을 사용하여 깊이를 제한하지 않는 한 -maxdepth
. 그러나 -L
옵션이나 -follow
조건자 4를 사용하지 않는 한 디렉토리에 대한 심볼릭 링크를 따르지 않습니다.
² 명령 대체에 의해 삭제된 후행 부분은 제외됩니다.
³ 음, 에서는 처음부터 비표준이 zsh
필요하지 않습니다 . 단지 재귀 glob 및 glob 한정자를 사용하거나 심볼릭 링크를 따르기만 하면 됩니다.find
-print0
var=( **/*(ND.) )
var=( ***/*(ND.) )
4그러나-L
/ -follow
는 행동에도 영향을 미칠 수 있다는 점에 유의하십시오 -type
. 일반 파일에 대한 기호 링크는 결국 여기에서 -type f
선택됩니다 . GNU를 통해 구현되면 , 없이 일반 파일에 심볼릭 링크하는 대신 with를 find
사용하여 일반 파일만 선택할 수 있습니다 .-xtype f
-L
-type f
-L
답변2
실수를 했습니다. 소프트 링크를 사용하고 있었는데 사용하지 않았습니다.찾다그리고-엘배너.
original_list=()
while IFS= read -r -d $'\0'; do
original_list+=("$REPLY")
done < <(find -L ./ -type f -print0)
작동합니다!