포함하는 배열과 포함된 글로브를 제외한 배열에서 작성된 파일 배열을 가져옵니다.

포함하는 배열과 포함된 글로브를 제외한 배열에서 작성된 파일 배열을 가져옵니다.

나는 다음을 수행하고 싶습니다 :

  • 프로세스에 포함할 기본 파일 컬렉션을 지정하는 전역 배열을 정의합니다.
  • 이 프로세스에서 제외할 파일을 지정하는 전역 배열을 정의합니다. 이 glob 배열에 의해 지정된 파일이 위 세트에 없는지는 나에게 중요하지 않습니다.
  • 배열 구축문서(glob 아님), 포함하는 glob 배열에 지정된 모든 파일을 가져오고 제외된 glob 배열에 속하는 모든 파일을 삭제합니다.

나는 이것으로 어려움을 겪고 있습니다. 진행 상황과 제가 시도한 작업에 대한 몇 가지 명확한 예를 보여주기 위해 다음과 같은 작업을 시도했습니다.

# List all files to potentially include in the process
files_to_include=(
    'utils/*.txt'
)

# List any files here that should be excluded from the above list
files_to_exclude=(
    '*dont-use.txt'
    'utils/README.md'
)

# Empty array of files
files=()

for file in ${files_to_exclude[@]}; do
    temp=find $files_to_include -type f \( -name '*.txt' -and -not -name $file \)
    files+=$temp
done

# I want this to be the total collection of files that I care about
echo ${files[@]}

분명히 이 for 루프 논리는 작동하지 않지만 적어도 시작하게 되었지만 여전히 이 작업을 수행하는 적절한 방법을 찾는 데 어려움을 겪고 있습니다. (출력을 할당하려고 할 때만 이상한 권한 거부 메시지가 표시됩니다. 왜 그런 일이 발생하는지 모르겠습니다 find. temp)

find내가 이해한 바로 는 grep. 이를 수행하는 방법에는 여러 가지가 있을 수 있지만 스크립트에서 "마법"을 가능한 한 적게 사용하고 싶습니다. 따라서 스크립트를 효율적이고 이해하기 쉽게 만들 수 있도록 도와주세요.

내가 아는 한, include 배열의 모든 glob을 확장하고, 제외 배열의 모든 glob을 확장한 다음, include 배열에서 제외 항목을 빼는 프로시저가 필요합니다. 그러나 이는 매우 높은 수준이며 이를 구현하는 것은 나에게 어려운 일입니다.

감사합니다!

답변1

files_to_include당신 이 glob이 되고 싶은 것처럼 보이지만 files_to_exclude단지 패턴이어야 합니다. 그렇지 않으면 glob은 *dont-use.txt작동하지 않습니다.생산하다(파일 이름 생성또는경로명 확장다른 이름에 대한 와일드카드입니다) 따라서 utils/whatev-dont-use.txt파일을 제외하지 않으며 utils/*.txt단지 패턴인 경우에도 일치합니다 utils/.git/foo/bar/.txt.

zsh하나 있다~ 패턴으로 제외glob 연산자를 사용하면 다음을 수행할 수 있습니다.

set -o extendedglob
globs_to_include=(
  'utils/*.txt'
)

patterns_to_exclude=(
  '*dont-use.txt'
  'utils/README.md'
)

typeset -U files=(
  $~^globs_to_include~(${(j[|])~patterns_to_exclude})(ND.)
)

또는 필요하지 않은 경우 extendedglob사후 필터링을 위해 매개변수 확장 연산자를 사용합니다.patterns_to_exclude${array:#pattern}

typeset -U files=( $~^globs_to_include(N.) )
files=( ${files:#(${(j[|])~patterns_to_exclude})} )

두 배열이 모두 패턴이고 현재 작업 디렉터리 안이나 아래에 있는 모든 일반 파일의 경로와 일치시키려는 경우 다음과 같을 수 있습니다.

() {
  files=( ${${(M)@:#(${(j[|])~patterns_to_include})}:#(${(j[|])~patterns_to_exclude})} )
} **/*(ND.)

또는 단계별로 명확하게 설명하세요.

pattern_to_include="(${(j[|])patterns_to_include})"
pattern_to_exclude="(${(j[|])patterns_to_exclude})"
files=( **/*(ND.) )
files=( ${(M)files:#$~pattern_to_include} )
files=( ${files:#$~pattern_to_exclude} )

둘 다 글로벌이어야 한다면 다음과 같습니다.

typeset -U files_to_include=(
  utils/*.txt(ND.)
)
typeset -U files_to_exclude=(
  *don-use.txt(ND.)
  utils/README.md(ND.)
)
files=( ${files_to_include:|files_to_exclude} )

${A:|B}배열 빼기 연산자를 사용하십시오 .

이러한 zsh 관련 구문 중 일부에 대한 설명:

  • array=( elements ): bash가 마침내 2.0에서 배열 지원을 추가한 이후 일부 쉘에 의해 복사된 배열 선언입니다. Korn 쉘 과 유사합니다 set -A array -- elements.
  • **/: 재귀 와일드카드에 사용되는 모든 수준의 디렉터리입니다.
  • extendedglob~옵션: 운영자 필요
  • typeset -U array:배열 요소를 고유하게 만듭니다.
  • $~var: 콘텐츠가 $var스키마로 처리되도록 합니다.
  • $^array/more: 확장 기능을 element1/more element2/morecsh 스타일로 {element1,element2}/more멋지게 만듭니다.
  • ${(...)param}이는 매개변수 확장 플래그입니다. 배열의 요소를 추가하는 j[|]데 사용됩니다 .j|
  • (ND.): 이것은 glob 한정자입니다. 파일 유형을 제한하기 위해 N해당 glob, Ddot globdot에 대해 nullglob을 활성화합니다..정기적인.
  • ${array:#pattern}패턴과 일치하는 요소를 필터링합니다. (M)로고와 함께 ,필터링.
  • () { body; } args: 익명 함수가 몇 가지 인수를 전달했습니다( 일명 명명된 함수와 마찬가지로 $@aka $argv$1... 에서 사용 가능 $2).

답변2

인용문이 당신에게 불리하기보다는 당신에게 유리하게 작용하도록 하십시오. 글로브를 인용하지 말고 쉘이 글로브를 확장하도록 하십시오. 변수가 와일드카드로 처리되는 것을 방지하려면 변수 주위에 큰따옴표를 사용하십시오. @큰따옴표를 포함한 배열 특수 기호를 입력하는 것을 잊지 마세요 .

includes=( utils/*.txt )
excludes=( *dont-use.txt utils/README.md )

# Convert array to hash so we can easily index it
declare -A excludes_hash
for i in "${excludes[@]}"
do
    excludes_hash["$i"]=1
done

# Build list of files
files=()
for i in "${includes[@]}"
do
    [ -z "${excludes_hash[$i]}" ] && files+=("$i")
done

# Total collection of files that I care about
printf "%s\n" "${files[@]}"

관련 정보