find
이유 를 이해할 수 없으며 locate
C 및 Python 소스 파일에서는 다르게 작동합니다. 내 목표는 특정 언어의 소스 파일 수와 해당 소스 코드 줄의 합계를 계산하는 것입니다. AND를 사용하여 출력을 비교합니다( find
AND 를 실행하기 직전에 현재 결과가 보고되는지 확인합니다 ).locate
updatedb
sudo
locate
C 파일의 경우 이는 예상대로 작동하며 소스 파일 수는 동일합니다.
$ find / -name *.c |& grep -v "Permission denied" | wc -l
1056
$ locate *.c | wc -l
1056
를 사용하면 xargs
소스 코드 줄의 합도 동일합니다.
$ locate *.c | xargs wc -l | tail -3
138 /usr/src/kernels/3.10.0-693.el7.ppc64/scripts/selinux/genheaders/genheaders.c
147 /usr/src/kernels/3.10.0-693.el7.ppc64/scripts/selinux/mdp/mdp.c
705376 total
$ find / -name *.c |& grep -v "Permission denied" | xargs wc -l | tail -3
2994 /opt/Python-3.6.2/Objects/listobject.c
821 /opt/Python-3.6.2/Objects/bytes_methods.c
705376 total
테스트를 위해서만 .java
확장자가 있는 파일에도 작동합니다. 동일한 일관된 결과를 얻습니다. 그러나 Python 파일(예: 확장자)에 대해 .py
동일한 작업을 반복 하면
소스 파일 번호가 일치합니다.
$ find / -name *.py |& grep -v "Permission denied" | wc -l
9249
$ locate *.py | wc -l
9249
그러나 Python 파일에 대한 코드 줄의 합은 매우 다른 결과를 제공합니다.
$ locate *.py | xargs wc -l | tail -3
wc: /usr/lib/python2.7/site-packages/setuptools/script: No such file or directory
wc: template: No such file or directory
wc: (dev).py: No such file or directory
wc: /usr/lib/python2.7/site-packages/setuptools/script: No such file or directory
wc: template.py: No such file or directory
220 /usr/src/kernels/3.10.0-693.el7.ppc64/scripts/rt-tester/rt-tester.py
129 /usr/src/kernels/3.10.0-693.el7.ppc64/scripts/tracing/draw_functrace.py
753350 total
$ find / -name *.py |& grep -v "Permission denied" | xargs wc -l | tail -3
wc: /usr/lib/python2.7/site-packages/setuptools/script: No such file or directory
wc: template: No such file or directory
wc: (dev).py: No such file or directory
wc: /usr/lib/python2.7/site-packages/setuptools/script: No such file or directory
wc: template.py: No such file or directory
1919 /opt/Python-3.6.2/python-gdb.py
69 /opt/Python-3.6.2/python-config.py
1034101 total
왜 이런 일이 일어나는지 설명해 줄 수 있나요? Python 파일과의 차이점은 무엇입니까? (파일 형식과 관련이 있다는 사실이 정말 믿기지 않지만 혼란스럽습니다.) 내가 여기서 무엇을 놓치고 있는 걸까요?
Ubuntu와 RH에서도 똑같은 이상한 결과가 나타납니다.
저는 updatedb
run 을 사용 sudo
하지만 이 모든 명령을 일반 사용자로 실행합니다.
답변1
명령에 문제가 많습니다.
첫째, 이름이 일치하는 파일이 없는 디렉터리에서 실행하면 locate *.c
일치하는 파일만 찾습니다. 그렇지 않으면 쉘이 일치하는 파일 목록으로 확장됩니다. 아마도 이런 일이 발생하지 않거나 더 적은 수의 일치 항목을 얻게 되지만 이와 같이 인용되지 않은 와일드카드를 남겨 두는 것은 나쁜 습관입니다.*.c
*.c
*.c
~ 할 것이다어느 날 당신을 물다. (이것은 이 사이트의 공통 주제입니다.) find -name *.c
대신에 동일하게 적용됩니다.
locate '*.c' …
find / -name '*.c' …
또는 그런 것.
몇 가지 일반적인 원인이 있으며 locate
다양한 find
결과가 나타날 수 있습니다. 귀하의 경우에는 동일한 클릭수가 발생하므로 해당 사항이 적용되지 않는 것 같지만 다시 한 번 이에 유의해야 합니다.
locate
마지막 실행 결과를 캐시합니다updatedb
. 보통 저녁에 한 번 진행됩니다.find
명령이 실행될 때마다 계산되는 결과입니다.- 시스템,
locate
사용 중인 구현 및 구성 방법에 따라 공개적으로 액세스할 수 있는 파일(예: mlocate 또는 slocate가 아닌 GNU findutils)만 볼 수 있거나 사용자가 사용하는 파일의 복사본을 생성할 수 있습니다. 근사치를 보고 있습니다. 액세스를 허용합니다(예: 파일에 액세스하려고 시도하는 애플리케이션을 구별하는 Linux 보안 모듈과 관련된 복잡한 설정이 있기 때문에). - to와 to는 이 패턴에서 동일한 의미를 가지지만
*SUFFIX
(슬래시나 와일드카드가 포함되지 않는다고 가정), 다른 패턴에서는 그렇지 않습니다. 예를 들어, ~보다는 ~와 동일합니다.locate
find -name
SUFFIX
locate foo
find / -name '*foo*'
find / -name 'foo'
find
문제를 일으킬 수 있지만 그렇지 않을 수도 있는 또 다른 점은 명령의 데이터 처리 부분에 오류 메시지를 연결했다는 것입니다 . 포함된 행을 제거하면 Permission denied
이름의 일부로 이를 포함하는 파일이 누락되고(아무 것도 없을 수도 있음) 포함되지 않은 모든 오류 메시지가 Permission denied
입력 행으로 해석됩니다. 데이터 출력과 오류 출력을 혼합하는 것은 좋은 생각이 아니며 여기서는 말도 안됩니다. 오류를 무시하려면 다음으로 리디렉션하세요 /dev/null
.
find … 2>/dev/null | …
확실히 당신을 짜증나게 하는 것은 xargs
예상되는 입력 구문이 생성된 구문과 다르다는 것입니다 find
. input 에서 xargs
개행 문자뿐만 아니라 모든 공백은 항목을 구분합니다. 이 세 문자 \'"
도 특별히 구문 분석됩니다. 파일 이름에는 공백이 일반적이며 /
널 바이트를 제외한 모든 문자가 허용됩니다. xargs
입력을 받는 라인 중 하나는 다음과 같습니다.
/usr/lib/python2.7/site-packages/setuptools/script template (dev).py
의 경우 , 및 xargs
의 세 가지 항목이 있습니다 . 이제 오류 메시지의 원인이 명확해졌습니다./usr/lib/python2.7/site-packages/setuptools/script
template
(dev).py
wc
이에 대한 몇 가지 해결책이 있습니다. 하나는 sum 에 find
null로 구분된 형식을 사용하는 것 입니다 xargs
. 이는 모든 파일 이름에 적용되며 개행 문자가 포함된 파일 이름에도 적용됩니다(허용되지만 일반적이지 않음).
find / -name '*.py' -print0 | xargs -0 wc -l | tail -3
또 다른 접근 방식은 문제가 있는 것을 잊어버리고 xargs
명령 find
을 직접 호출하는 것입니다.
find / -name '*.py' -exec wc -l {} + | tail -3
첫 번째 솔루션이 귀하의 locate
구현에 적합할 수 있습니다. 옵션이 있는지 확인하십시오 -0
. 두 번째 해결책은 에 관한 것입니다 find
. 줄 바꿈으로 구분된 출력을 사용하려고 locate
하고 GNU 버전이 있는 경우 이를 사용 하여 어떤 형태의 인용 없이 줄 바꿈으로 구분된 입력을 구문 분석하도록 xargs
할 수 있습니다 .-d '\n'
locate '*.py' | xargs -d '\n' wc -l | tail -3
이것이 당신의 주요 문제입니다. 또 다른 문제는 명령줄에 최대 길이가 있다는 것입니다. 명령 xargs
(또는 -exec … {} +
action find
)은 명령줄에 가능한 한 많은 파일 이름을 입력하고, 모두 맞지 않으면 명령(여기서 wc -l
)이 각 파일 배치에 대해 한 번씩 여러 번 실행됩니다. 를 사용하면 tail -3
마지막 두 파일과 마지막 배치의 총 개수만 볼 수 있습니다(마지막 배치에 최소 두 개의 파일이 있다고 가정). 이전 배치의 파일은 이 출력에 반영되지 않습니다. find
와 locate
파일을 동일한 순서로 보고하지 않을 수 있으므로 결과가 다를 수 있습니다 .
최대 길이 문제를 해결하는 방법은 데이터로 수행하려는 작업에 따라 다릅니다. 원하는 것이 전체인 경우 한 가지 접근 방식(파일 이름에 개행 문자가 없다고 가정)은 모든 total
줄을 계산하는 것입니다.
… | xargs -d '\n' wc -l | awk '/^[0-9]+\ttotal$/ {total += $1} END {print total}'