디렉터리와 해당 하위 디렉터리에서 모든 .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
분사또는경로명 확장그리고 줄 길이 제한을 초과하지 않고 다음을 사용하십시오(여기서 해당 및 옵션이 xargs
GNU 구현이라고 가정).-d
-r
xargs -r -d'\n' -I{} find {} -name '*.c' <list_of_dir
진정한 보안을 위해서는 줄 바꿈으로 구분된 목록보다는 NUL로 구분된 디렉터리 목록을 사용해야 합니다. list_of_dir0
NUL로 구분된 디렉토리 목록이 포함된 경우 다음을 사용하십시오.
xargs -r -0 -I{} find {} -name '*.c' <list_of_dir0
어떻게 작동하나요?
-r
find
디렉토리 목록이 비어 있지 않으면 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
오류 메시지가 표시되거나 현재 디렉터리에서 검색됩니다).
이는 또한 술어로 시작하거나 술어가 -
아닌 줄이 없다고 가정합니다(대부분의 술어는 ( , , ...) 로 시작 하지만, , ... 도 있습니다).find
find
-
-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
디렉터리 이름을 파일에 넣고 디렉터리 이름을 사용하여 찾기를 실행하고 결과를 인쇄합니다. 아포스트로피는 파일 이름의 모든 공백이나 예약 문자를 처리합니다.