여러 파일 확장자를 반복하는 방법에 대한 다양한 주제를 보았지만 대부분의 경우 목록이 정의되어 있습니다.
예:
for file in ${arg}/**/*.{txt,h,py}
do
....
done
보시다시피 .TXT
파일은 무시됩니다. 안타깝게도 이 질문에 답변한 사람은 bash4에서만 작동한다고 말했습니다. 하지만 내 설정에서는 bash3.x를 사용합니다.
이 작업을 수행하는 방법에 대한 아이디어가 있습니까?
답변1
bash
여기에서 다음 을 설정할 수 있습니다 nocaseglob
.
shopt -s nocaseglob
for file in "$arg"/**/*.{txt,h,py}
do
....
done
shopt -u nocaseglob
noclaseglob
bash
2.01 이후 모든 버전 에서 작동하지만 4.0 이상이 **
필요합니다 (그리고 수정된 4.3 bash
까지 심볼릭 링크를 따릅니다 ). 공백이나 와일드카드가 포함되면 문제가 발생하므로 bash
따옴표를 수정해야 합니다 .$arg
사용하지 않고 **
다음을 수행할 수 있습니다.
find "$arg" \( -iname '*.txt' -o -iname '*.h' -o -iname '*.py' \) -exec bash -c '
for file; do
...
done' bash {} +
그러면 찾고 있는 모든 파일을 찾아서 새 bash 인스턴스에 별도의 인수로 전달한 다음 해당 파일을 반복하게 됩니다. 각 파일 작업이 단일 명령인 경우 새 bash 인스턴스를 건너뛰고 명령을 직접 사용할 수 있습니다.
고쳐 쓰다
아래 Stephane의 의견에 따르면 POSIX 호환 솔루션은 다음과 같습니다.
find "$arg" \( -name '*.[tT][xX][tT]' -o -name '*.[hH]' -o -name '*.[pP][yY]' \) \
-exec sh -c '
for file do
...
done' sh {} +
답변2
대신 사용하십시오 zsh
:
setopt extendedglob
for f ($arg/**/*.(#i)(txt|h|py)(N.)) {
...
}
**/
: 모든 수준의 하위 디렉터리(#i)
나머지 glob(예:~(i)
) 에 대해 대소문자를 구분하지 않는 일치를 켜는 것입니다ksh93
.(N.)
글로벌 예선입니다.N
일치하는 파일이 없으면 오류를 반환하지 않고.
일반 파일(find
s 와 동일-type f
)을 선택하는 것입니다.D
도트(숨겨진) 파일과 일치하도록 거기에 하나를 추가하고 숨겨진 디렉터리로 이동할 수 있습니다(find
기본값과 동일).
답변3
간단한 것은 어떻습니까?
for file in "$(ls -1 | grep -iE '\.txt|\.py|\.h')";
do
....
done
또 다른 간단한 옵션은 다음과 같습니다.
find . -maxdepth 1 -iname '*.txt'; find . -maxdepth 1 -iname '*.py'; find . -maxdepth 1 -iname '*.h';
bash에서 find를 $() 대괄호로 묶어 목록을 얻을 수 있습니다.