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포함된 모든 파일 에는 작업이 적용된다는 아이디어입니다 . 이 특별한 경우에는 stdout으로 인쇄하여 결과가 올바른지 확인하세요.

문제는 그 진술을 넘어서는 것이 아무것도 없다는 것입니다 if. 그래서 나는 무엇을 놓치고 있는지 모르겠습니다. 작동하는 것은 라인뿐입니다 printf "input....

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

답변1

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

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

어느 부분에나 나타날 수 있는 파일 이름을 원하면 _AACBash에서 다음을 수행할 수 있습니다.

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

중괄호 확장은 여러 개의 개별 글로브를 생성하는 반면, @(..)단 하나의 글로브만 생성합니다. (예 *.{foo,bar}: 와 동일 *.foo *.bar) nullglobset을 사용하면 일치하지 않는 항목은 중요하지 않지만, 설정한 경우 failglob일치하지 않는 항목 하나만 설정해도 전체 명령이 실패할 수 있습니다.

답변2

스크립트의 내용은 다음과 같습니다.

  if grep -qF _AAC $file; then

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

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

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

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

관련 정보