대소문자를 구분하지 않고 여러 파일 확장자를 반복하는 방법은 무엇입니까?

대소문자를 구분하지 않고 여러 파일 확장자를 반복하는 방법은 무엇입니까?

여러 파일 확장자를 반복하는 방법에 대한 다양한 주제를 보았지만 대부분의 경우 목록이 정의되어 있습니다.

예:

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

noclaseglobbash2.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일치하는 파일이 없으면 오류를 반환하지 않고 .일반 파일( finds 와 동일 -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를 $() 대괄호로 묶어 목록을 얻을 수 있습니다.

관련 정보