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