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
어느 부분에나 나타날 수 있는 파일 이름을 원하면 _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
중괄호 확장은 여러 개의 개별 글로브를 생성하는 반면, @(..)
단 하나의 글로브만 생성합니다. (예 *.{foo,bar}
: 와 동일 *.foo *.bar
) nullglob
set을 사용하면 일치하지 않는 항목은 중요하지 않지만, 설정한 경우 failglob
일치하지 않는 항목 하나만 설정해도 전체 명령이 실패할 수 있습니다.
답변2
스크립트의 내용은 다음과 같습니다.
if grep -qF _AAC $file; then
이는 "이름이 지정된 파일의 내용에 $file
리터럴 문자열이 포함되어 있으면 _AAC
...." 블록의 내용을 실행한다는 의미입니다 then
.
_AAC
변수 확장으로 인해 발생하는 문자열에서 대신 검색하려는 경우 $file
(예: _AAC가 파일 이름 자체에 나타나는지 확인하기 위해), 에서 다음을 bash
작성해야 합니다.
if grep -qF _AAC <<< "$file"; then
또는 @roaima가 지적했듯이 검색 중인 리터럴 문자열이 와일드카드 파일 사양에 포함될 수 있습니다.