루프 및 변수와 함께 find 및 grep을 사용하는 방법은 무엇입니까?

루프 및 변수와 함께 find 및 grep을 사용하는 방법은 무엇입니까?

내 디렉토리에 많은 파일이 있습니다.

# 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

-xgrep전체 줄이 일치하도록 합니다 . -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빈 문자열로 확장됩니다. 쉘이 확장하는 것을 원하지 않습니다(임베딩과 유사한 결함으로 인해 어려움을 겪게 됨 {}).

관련 정보