정수 배열을 기반으로 파일 목록을 필터링하시겠습니까?

정수 배열을 기반으로 파일 목록을 필터링하시겠습니까?

'라는 이름의 이미지가 많이 포함된 폴더가 있습니다.클립 01234-randomlongstring.png", 어디01234임의의 5자리 숫자입니다. 나한테도 배열이 있어요."클립 번호"를 정수 목록으로 사용합니다.

이제 "파일"의 숫자와 일치하는 모든 파일 이름을 포함하는 "파일" 목록을 만들고 싶습니다.클립 번호"어레이. 어떻게 해야 하나요?

결과 출력은 내가 만든 현재 목록(모든 파일)과 동일한 방식으로 처리할 수 있는 것이어야 합니다. files=($(printf "%s\n" *.* | sort -V | tr '\n' ' '))

답변1

루프에서:

shopt -s nullglob

files=()
for number in "${clipnumbers[@]}"; do
    printf -v pattern 'clip%s-*.png' "$number"
    files+=( $pattern )
done

이는 숫자를 반복하고 각 숫자에 대한 파일 이름 와일드카드 패턴을 생성합니다. 패턴은 패턴과 일치하는 파일 이름을 배열에 추가하도록 확장됩니다 files. 쉘 nullglob옵션을 사용하면 일치하지 않는 패턴이 확장되지 않은 상태로 두는 대신 아무 것도 확장되지 않습니다.


사용 find(현재 디렉터리 아래의 모든 디렉터리로 반복하고 발견된 각 파일에 대해 일부 작업을 수행하는 경우):

patterns=()
for number in "${clipnumbers[@]}"; do
    printf -v pattern 'clip%s-*.png' "$number"
    patterns+=( -o -name "$pattern" )
done

find . -type f \( "${patterns[@]:1}" \) -exec action-to-perform-on-files {} \;

확장명 목록에서 첫 번째 문자를 제거합니다 :1.-opatterns

이는 파일 검색과 파일에 대한 일부 작업 수행을 결합합니다. 그럴 것이다실패하다배열에 수천 개의 숫자가 포함된 경우 clipnumbers(매개변수 목록이 너무 길어집니다).

답변2

옵션 1

~처럼코살로난다의 답변그러나 반복 대신 배열 확장을 사용하십시오.

설정

$ touch clip12710-x.png  clip30443-x.png  clip57592-x.png  clip76672-x.png  clip93493-x.png
$ declare -a array=([0]="30443" [1]="76672" [2]="42424")

배열에는 일치할 것으로 예상되는 두 개의 항목만 포함되어 있습니다. 파일 이름의 일부 클립은 다음과 같습니다.아니요존재하고 클립 번호가 array존재하며 어디에아니요파일 이름으로 존재합니다.

구현하다

$ shopt -s nullglob
$ pfiles=( "${array[@]/#/clip}" )
$ oIFS="$IFS"
$ IFS=
$ pfiles=( ${pfiles[@]/%/-*.png} )
$ IFS="$oIFS"
$ declare -p pfiles
declare -a pfiles=([0]="clip30443-x.png" [1]="clip76672-x.png")

큰따옴표는 첫 번째 할당에는 조심스럽게 포함되지만 두 번째 할당에는 포함되지 않습니다. 초기 할당은 숫자의 "배열" 배열을 부분 파일 이름의 "pfiles" 배열로 변환합니다.접두사문자열의 각 요소에 대해 clip. 두 번째 과제추가-*.png배열의 각 요소에 대한 와일드카드입니다. 이 할당에는 따옴표가 없기 때문에 쉘이 각 요소 $IFS(일반적으로 공백, 탭 및 줄 바꿈)를 분할할 수 있지만 지금은 IFS를 비어 있도록 덮어씁니다. 그런 다음 쉘은 결과를 "글로브"합니다. 이는 여기서 원하는 것입니다. "clip...*-png" 이름을 일치하는 파일 이름으로 확장합니다. 쉘 옵션이 설정되면 nullglob일치하지 않는 와일드카드 문자가 제거됩니다. 최종 결과는 원래 배열의 클립 번호와 일치하는 pfiles의 파일 배열입니다.


옵션 #2

(남용확장된 와일드카드:

shopt -s extglob nullglob
declare -a array=([0]="30443" [1]="76672" [2]="42424")
oIFS="$IFS"
IFS='|'
p="${array[*]}"
IFS="$oIFS"
pfiles=( clip@($p)-*.png )

이는 IFS를 파이프 기호로 설정하여 수행됩니다 |. 따라서 후속 p할당은 array[*]파이프 array(현재 $IFS의 첫 번째 문자)로 요소를 연결합니다. 파이프는 확장 globbing 모드의 옵션 사이에 bash의 확장 globbing 구문에 필요한 구분 기호입니다. 마지막 줄은 우리가 만든 확장된 glob 패턴과 일치하는 파일 배열로 확장됩니다.

  • 에서 시작하다clip
  • 이제 변수에 포함된 지정된 패턴(클립 번호) 중 하나를 포함합니다.p
  • 그럼 -뭐든지
  • 그리고 끝나는.png

nullglob클립 배열이 기존 파일 이름과 겹치지 않는 경우 쉘 옵션이 필요합니다.

답변3

그리고 zsh:

clipnumbers=(01234 33333)
files=(clip$^clipnumbers-*.png(N.))

이렇게 하면 각 클립 번호에 대한 글로브가 확장됩니다. 또는 배열을 전역 대체 연산자로 변환할 수 있습니다.

files=(clip(${(j:|:)~clipnumbers})-*.png(N.))

답변4

mapfile -t files <  <( shopt -s nullglob ; printf "%s\n" $(printf "clip%s-*.png " "${clipnumbers[@]}" ) )
  • mapfile -t files후행 개행 문자를 제거하여 파일의 행을 배열로 읽습니다.
  • shopt -s nullglob존재하지 않는 패턴을 빈 문자열로 확장
  • printf "%s\n" ...한 줄에 하나씩 패턴을 확장합니다.
  • $(printf "clip%s-*.png " "${arr[@]}") )빌드 모드.

관련 정보