grep은 for 루프에서 파일 이름을 처리할 수 없습니다.

grep은 for 루프에서 파일 이름을 처리할 수 없습니다.

Bash 스크립팅을 배우면서 for 루프에 중첩된 grep을 사용하여 결과를 필터링하려고 합니다.

sample filenames:
  this-file_AAC.txt
  this-other_file_AAAC.txt
  yep-a-file_AAC.nfo
  oops_another_one.reamde

스크립트는 다음과 같습니다.

shopt -s globstar nullglob dotglob
for file in ./**/*.{txt,reamde,nfo}; do
  printf "input: ${file}\n"
  if grep -qF _AAC $file; then
    printf "output: ${file}\n"
    # do stuff with $file
  fi
done

이 특별한 경우에는 포함된 모든 파일 _AAC에 작업이 적용되며, 결과가 올바른지 확인하기 위해 표준 출력으로 인쇄하면 됩니다.

문제는 그 어떤 것도 if진술을 초월할 수 없다는 것입니다. 그래서 제가 모르는 것이 빠졌네요. 작동하는 유일한 것은 이 printf "input...줄입니다.

내가 무엇을 놓치고 있나요?

답변1

마지막 파일 이름 부분에 이름이 지정된 모든 파일을 일치시키려면 .../something_AACxyz해당 부분을 glob 패턴/와일드카드에 직접 추가하세요._AAC_AAC

for file in ./**/*_AAC*.{txt,reamde,nfo}; do

_AAC파일 이름을 어떤 부분에나 표시 하려면 Bash에서 다음을 수행할 수 있습니다.

for file in ./**/*.{txt,reamde,nfo}; do
    if [[ $file == *_AAC* ]]; then
         echo "'$file' contains _AAC"
    else
         echo "'$file' has NO _AAC"
    fi
done

여기서는 glob과 일치하는 파일도 얻을 수 있지만 _AAC.


어쨌든 Bash에서는 중괄호 확장을 사용하는 대신 extglob패턴을 활성화하고 재정의 할 수도 있습니다 .@(...|...)

for file in ./**/*_AAC*.@(txt|reamde|nfo); do

중괄호 확장은 @(..)단일 glob이지만 여러 개의 다른 glob을 생성합니다. (즉, *.{foo,bar}와 동일 *.foo *.bar) nullglobset을 사용할 때 일치하지 않는 항목은 중요하지 않지만, set을 사용하면 failglob일치하지 않는 항목 하나만 있어도 전체 명령이 실패하게 됩니다.

답변2

귀하의 스크립트는 다음과 같이 말합니다:

  if grep -qF _AAC $file; then

이는 "지정된 파일의 내용에 $file리터럴 문자열이 포함되어 있으면 _AAC..." 블록의 내용을 실행한다는 의미입니다 then.

_AAC변수 확장으로 생성된 문자열 내에서 검색하려면 ( $file예: _AAC가 파일 이름 자체에 나타나는지 확인) 에서 다음을 bash작성해야 합니다.

  if grep -qF _AAC <<< "$file"; then

또는 @roaima가 지적했듯이 검색 중인 리터럴 문자열이 와일드카드 파일 사양에 포함될 수 있습니다.

관련 정보