파일에 저장된 디렉터리 목록을 find 명령에 전달합니다.

파일에 저장된 디렉터리 목록을 find 명령에 전달합니다.

디렉터리와 해당 하위 디렉터리에서 모든 .c 파일은 다음을 통해 찾을 수 있습니다.

find /user/home/me/tests/ -name \*\.c

디렉토리 목록은 이제 "list_of_dir" 파일에 저장됩니다.

/user/home/me/test1
/user/home/me/test2
/user/home/me/test3
...

해당 파일과 해당 하위 디렉터리에 있는 모든 .c 파일을 찾기 위해 find 명령을 어떻게 제공할 수 있나요?

미리 감사드립니다.

편집: 내 기본 쉘은 tcsh입니다.

답변1

파일에 줄 바꿈으로 구분된 디렉터리 목록이 있고 해당 목록을 안전하게 전달 list_of_dir하려는 경우find분사또는경로명 확장그리고 줄 길이 제한을 초과하지 않고 다음을 사용하십시오(여기서 해당 및 옵션이 xargsGNU 구현이라고 가정).-d-r

xargs -r -d'\n' -I{} find {} -name '*.c' <list_of_dir

진정한 보안을 위해서는 줄 바꿈으로 구분된 목록보다는 NUL로 구분된 디렉터리 목록을 사용해야 합니다. list_of_dir0NUL로 구분된 디렉토리 목록이 포함된 경우 다음을 사용하십시오.

xargs -r -0 -I{} find {} -name '*.c' <list_of_dir0

어떻게 작동하나요?

  • -rfind디렉토리 목록이 비어 있지 않으면 xargs를 실행하지 않도록 지시하십시오 .

  • -0입력 시 NUL로 구분된 목록을 예상하도록 xargs에 지시합니다. 이는 -d'\n'개행으로 구분된 목록을 기대하도록 xargs에 지시하는 것보다 더 안전한 대안입니다.

  • - xargs에게 find 명령에서 문자가 보이는 위치 I{}에 디렉토리를 배치하도록 지시합니다 (한 번에 하나씩, 각 디렉토리에 대해 하나의 호출이 실행됩니다).{}find

답변2

$ (echo /tmp; echo /var/tmp) > file
$ find $(cat file) -prune
/tmp
/var/tmp
$ 

하지만! 디렉토리 이름에 개행 문자가 있거나 파일 이름 목록이 execve(2)최대 인수에 비해 너무 길면 이는 좋은 생각이 아닐 수 있습니다. tcsh오늘날의 Bourne 쉘이 좋아하지 않는 백틱 $(...)테이블을

% find `cat file` -prune
/tmp
/var/tmp
% 

하지만 이것은 Bourne의 쉘에서 발생하는 모든 동일한 문제로 인해 다시 어려움을 겪습니다.

답변3

에서 tcsh명령 대체를 인용하면 다음과 같이 분할됩니다.비어 있지 않은 각 줄마다 하나씩기본적으로 이것이 정확히 원하는 것과 같으므로 다음과 같이 할 수 있습니다.

find -- "`cat list.txt`" -name '*.c'

POSIX와 유사한 셸에서는 다음을 수행해야 합니다.

(set -o noglob; IFS='
'; find -- $(cat list.txt) -name '*.c')

같은 목적을 달성합니다.

여기에는 비어 있지 않은 줄이 하나 이상 포함되어 있는 것으로 가정됩니다 list.txt(그렇지 않으면 구현에 따라 find오류 메시지가 표시되거나 현재 디렉터리에서 검색됩니다).

이는 또한 술어로 시작하거나 술어가 -아닌 줄이 없다고 가정합니다(대부분의 술어는 ( , , ...) 로 시작 하지만, , ... 도 있습니다).findfind--ok-print-type!()

이는 또한 list.txt명령 매개변수의 최대 크기에 맞도록 충분히 작다고 가정합니다.

또 다른 옵션은 를 사용하는 것입니다 xargs.

<list.txt sed 's/"/"\\""/g;s/.*/"&"/'|xargs tcsh -c 'find $argv:q -name "*.c"'

sed여기서 각 줄은 에서 이해할 수 있는 형식으로 인용됩니다 xargs.

위와 동일한 제한이 있지만, 이를 방지하기 위해 가능한 한 많은 명령을 실행하여 인수 수에 대한 제한을 해결해야 하며 find, 가정하는 내용이 list.txt현재 로케일에서 유효한 텍스트라고 가정해야 합니다. 일부 xargs구현에서는 매개변수의 최대 크기에 대한 제한이 다소 낮으며, 이는 경로의 최대 크기보다 훨씬 작을 수 있습니다.

답변4

또 다른 방법은 다음 코드를 사용하는 것입니다.

(echo directory1 ; echo directory2 ; echo directory3) > file
for d in $(cat file); do find $d -name '*.c'; done

디렉터리 이름을 파일에 넣고 디렉터리 이름을 사용하여 찾기를 실행하고 결과를 인쇄합니다. 아포스트로피는 파일 이름의 모든 공백이나 예약 문자를 처리합니다.

관련 정보