내 디렉토리에 많은 파일이 있습니다.
# ls -1
file1
file2
file3
file4
file5
file6
file7
file8
file9
file10
작업은 다음보다 오래된 것을 찾는 것입니다 file5
. 나는 이것을 할 수 있습니다
# find . ! -newer file5
./file1
./file2
./file3
./file4
./file5
이제 위의 내용 중 일부/전체에 대한 참조가 포함된 파일이 생겼습니다.
# logfile=log
cat ${logfile}
/var/log/app/file1
/var/log/app/file3
/var/log/app/file5
이제 file5보다 오래되고 로그 파일에도 있는 파일 목록만 원합니다. 결과 목록은 다음과 같습니다.
file1
file3
file5
이와 같은 파일 이름에서 파일 이름을 찾으려고 했지만 작동하지 않습니다.
find . ! -newer file4 -exec bash -c 'for i in {}; do grep $i ${logfile}; done' \;
답변1
/var/log/app
그러면 디렉토리가 대신 find . ! -newer file5
실행 됩니다 find /var/log/app ! -newer /var/log/app/file5
. 이런 식 find
으로 의 출력은 log
.
find
그런 다음 다음 중 하나만 사용하여 출력을 필터링할 수 있습니다 grep
.
find /var/log/app ! -newer /var/log/app/file5 | grep -xFf log
-x
grep
전체 줄이 일치하도록 합니다 . -F
패턴을 고정 문자열로 처리하도록 지시합니다. -f
지정된 파일에서 패턴을 읽습니다. 이러한 옵션은 이식 가능합니다.
대안으로(또는 /var/log/app
현재 작업 디렉터리가 아니지만 그런 척하려는 경우) 두 번째 로그를 만들어 해당 항목이 ./…
원래 작업 디렉터리의 일반 형식과 일치하도록 합니다 find
.
sed 's|^/var/log/app/|./|' log > log2
새 로그에는 find
원래 명령 출력을 필터링하는 데 사용할 수 있는 상대 경로가 포함되어 있습니다.
find . ! -newer file5 | grep -xFf log2
노트:
! -newer file5
"보다 나이가 많다"는 뜻은 아닙니다file5
. 이 테스트는file5
동일하게 오래된 파일과 일치합니다.- 추가 옵션/테스트(예:
-maxdepth 1
)-type f
가 유용할 수 있습니다.
당신의 시도:
find . ! -newer file5 -exec bash -c 'for i in {}; do grep $i ${logfile}; done' \;
여러 면에서 부족하거나 차선책:
- 로그 파일은 데이터로, 경로 이름은 패턴으로 생각합니다
find
. 위에 표시된 것처럼 그 반대의 경우도 더 쉽습니다. - 내부 맥락에서
bash
및$i
는${logfile}
인용되지 않습니다.큰따옴표로 묶어야 합니다. - 쉘 코드를 삽입했습니다
{}
. 일반적으로 임베딩은{}
따옴표가 없는 변수처럼 동작하지만, 어떻게 인용하더라도명령 주입 취약점. 그래서 더 나쁩니다. - (대신) 하나의 경로 이름을
-exec … \;
which로 바꾸었지만 여전히 많은 경로 이름을 예상한 것처럼 작성했습니다 . 일반적으로 내부 쉘은 대체하는 내용을 두 단어 이상으로 해석할 수 있습니다. 파일 이름 생성이 트리거될 수도 있습니다. 이는 위에서 언급한 "따옴표가 없는 변수와 같은" 동작입니다. 따라서 일반적으로 순환적인 "경로 이름"이 많이 생길 수 있지만 예상한 것과는 다릅니다.{}
-exec … {} +
for i in {}
{}
logfile
환경에 없으므로 내부 쉘은$logfile
빈 문자열로 확장됩니다. 쉘이 확장하는 것을 원하지 않습니다(임베딩과 유사한 결함으로 인해 어려움을 겪게 됨{}
).