사용자가 지정한 확장자를 가진 파일 찾기

사용자가 지정한 확장자를 가진 파일 찾기

여러 파일 확장자를 쉼표로 구분된 문자열로 사용하고 이를 사용하여 특정 디렉터리 구조의 파일을 나열하는 스크립트를 작성 중이지만 제공되는 확장자 수는 다를 수 있습니다.

내가 사용하는 find 명령은 다음과 같습니다.

     find ./ -type f \( -iname \*.ksh -o -iname \*.cfg \)

여기서 사용자는 ksh 및 cfg 파일을 검색하고 있습니다. 그러나 사용자는 ksh, cfg 또는 그 이상의 확장만 찾을 수 있습니다. 여러 확장 프로그램에 공통된 검색 패턴을 만드는 방법이 있습니까?

답변1

파일 이름 접미사를 별도의 명령줄 인수로 가져온다고 가정합니다(쉼표로 구분된 문자열을 처리하는 방법에 대한 정보는 답변의 끝 부분 참조).

#!/bin/sh

for suffix do
    set -- "$@" -o -iname "*.$suffix"
    shift
done

shift

find . -type f \( "$@" \)

스크립트가 호출됩니다.

./script.sh ksh cfg

$suffix위치 매개변수의 모든 접미사 를 -o -iname "*.$suffix".

shift통화 전의 유일한 문자 는 find제거됨 -o의 첫 번째 문자입니다 "$@".

ksh93또는 와 함께 배열 사용 bash:

#!/bin/ksh

name_opts=()

for suffix do
    name_opts+=( -o -iname "*.$suffix" )
done

find . -type f \( "${name_opts[@]:1}" \)

in은 배열의 첫 번째 (초기 ) 요소를 :1삭제합니다 ."${name_opts[@]:1}"name_opts-o


접미사를 쉼표로 구분된 문자열로 가져오려는 경우(즉, RCS 또는 CVS 저장소의 파일과 같이 파일 이름 접미사에 쉼표가 있는 파일을 찾기 위해 스크립트를 사용할 수 없음을 의미함) 문자열을 변환할 수 있습니다. $list, 배열 로 bash또는ksh93

set -f
suffixes=( ${list//,/ } )
set +f

또는sh

set -f
set -- $( printf '%s\n' "$list" | tr ',' ' ' )
set +f

또는

set -f; ifs=$IFS; IFS=','
set -- $list
set +f; IFS=$ifs; unset ifs

(이들은 위치 매개변수를 접미사 목록으로 설정합니다.)

set -f파일 이름은 쉼표를 대체하는 공백으로 문자열을 분할하기 위해 쉘에 의존하기 때문에 생성됩니다(와일드카드).아니요와일드카드에는 생성된 단어를 사용합니다. 그렇지 않으면 또는 등의 접미사에 대한 요청을 set -f올바르게 처리할 수 없습니다 .[ch]*

bash루프는 또는 다음 ksh에서 시작됩니다.

for suffix do ...

도착하다

for suffix in "${suffixes[@]}"; do ...

그리고 루프는 sh그대로 유지됩니다.

답변2

확장 정규식을 사용하여 -iregex여러 세그먼트를 바꿀 수 있습니다.-iname

그누 find:

find . -type f -regextype egrep -iregex '.*\.(ksh|cfg)$'

무료 BSD find:

find -E  . -type f -iregex '.*\.(ksh|cfg)$' 

변수에 이미 쉼표로 구분된 확장자가 있는 경우(예 $csep: ) 이를 정규식 대체( |)로 변환합니다. 첫 번째. 예를 들어

csep='ksh,sh,cfg,csv'
re="$(echo "$csep" | tr , '|')"
find . -type f -regextype egrep -iregex ".*\.($re)$"
#BSD: find -E . -type f -iregex ".*\.($re)$"

쉼표가 있는 확장을 지원해야 하는 경우 sed대신 을 사용하여 tr백슬래시로 이스케이프된 쉼표( \,)를 허용할 수 있습니다. 예를 들어

$ csep='ksh,sh,cfg,csv,c\,v'
$ re="$(echo "$csep" | sed -Ee 's/([^\]),/\1|/g')"
$ printf '%b\n' "$re"
ksh|sh|cfg|csv|c\,v

관련 정보