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
) nullglob
set을 사용할 때 일치하지 않는 항목은 중요하지 않지만, set을 사용하면 failglob
일치하지 않는 항목 하나만 있어도 전체 명령이 실패하게 됩니다.
답변2
귀하의 스크립트는 다음과 같이 말합니다:
if grep -qF _AAC $file; then
이는 "지정된 파일의 내용에 $file
리터럴 문자열이 포함되어 있으면 _AAC
..." 블록의 내용을 실행한다는 의미입니다 then
.
_AAC
변수 확장으로 생성된 문자열 내에서 검색하려면 ( $file
예: _AAC가 파일 이름 자체에 나타나는지 확인) 에서 다음을 bash
작성해야 합니다.
if grep -qF _AAC <<< "$file"; then
또는 @roaima가 지적했듯이 검색 중인 리터럴 문자열이 와일드카드 파일 사양에 포함될 수 있습니다.