"find" 명령이 배열과 유사한 요소를 반환하지 않는 경우 이 문제를 해결하는 방법

"find" 명령이 배열과 유사한 요소를 반환하지 않는 경우 이 문제를 해결하는 방법

Powershell에서는 다음과 같은 작업을 수행하는 데 익숙합니다.

> $python_files = get-childitem *.py
> echo $python_files[0]

get-childitem두 번째 명령을 사용 하면 배열과 유사한 객체가 반환되므로 첫 번째 파일을 추출할 수 있습니다 .

Bash에서는 다음 내용이 거의 동일하다는 것을 알고 있습니다.

> test=$(find . -iname '*.py')

그런데 첫 번째 항목을 얻지 못해서 문자열 같은 객체가 반환되는 줄 echo $test[0]알았어요 .find

명령에서 첫 번째 항목을 가져오는 일반적인 방법이 있습니까 find? 범용이란 명령 독립적이거나 grep.

답변1

Bash에서는 다음 내용이 거의 동일하다는 것을 알고 있습니다.

test=$(find . -iname '*.py')

그러나 echo $test[0]첫 번째 항목을 얻지 못했기 때문에 find가 문자열과 같은 객체를 반환한다고 가정합니다.

일부 값의 경우 "대략"입니다. 실제로 "대략" 값은 매우 대략적입니다.

파이프와 명령 대체는 파일과 같은 객체인 명령의 출력(표준 출력, stdout)을 읽는 데 의존합니다(물론 검색할 수 없습니다(예: 무작위 액세스)). 이것은 바이트 스트림입니다. 다음과 같이 직렬화되지 않는 한 데이터 구조의 전송을 허용하지 않습니다.바이트 시퀀스.

당신이 원하는 것은 파일 이름을 한 줄에 하나씩 인쇄하도록 test=$(find . -iname '*.py')요청한 find다음 쉘이 이를 string 으로 변수에 읽어들이도록 하는 것입니다 test. 변수에는 다음과 같은 내용이 포함됩니다 hello.txt<newline>there.txt. 이는 어느 정도 괜찮지만 쉘 배열이 아니므로 색인을 생성할 수 없으며 파일 이름에 개행 문자가 포함되어 있으면 중단됩니다. (또한 파일 이름에 공백이 포함되어 있으면 깨질 것입니다 for f in $(find...). 이는 다른 시나리오이고 단어 분리가 관련되어 있기 때문입니다.)

findBash에서 배열 의 출력을 읽으려면 readarray프로세스 대체(이것 <(...))를 사용할 수 있습니다.

readarray -d '' -t files < <(find ... -print0)
printf '%s\n' "Third element of array is '${files[2]}'"

-print0findNUL 바이트로 출력의 각 파일 이름을 종료하도록 지시합니다 . 이는 파일 이름에 나타날 수 없는 유일한 바이트이기 때문에 명시적 직렬화에 작동합니다. NUL을 구분 기호로 예상하도록 -d ''지시합니다 . readarray배열 인덱스는 다음에서 시작됩니다.Bash에서 (참조http://mywiki.wooledge.org/BashGuide/Arrays).

(이식성에 관해서: 모든 쉘이 어레이를 지원하는 것은 아니며 zsh는 지원하지만 약간 다르게 작동합니다. -print0또한 표준은 아니지만 널리 지원됩니다.)

또는 쉘 glob과 일치하는 파일 목록을 원하는 경우:

files=( *.py )

(일치하는 파일이 없는 경우 bash이 옵션을 설정하지 않으면 호출된 요소를 얻게 됩니다.)*.pynullglob

globstar여기서는 또는 dotglob다른 옵션을 사용할 수 있지만 extglob, 사용 가능한 옵션은 물론 쉘에 따라 다르며 find제공된 옵션과 다릅니다.

관련 정보