확장된 파일 이름에서 스키마 연결 배열 생성

확장된 파일 이름에서 스키마 연결 배열 생성

다음과 같은 줄 바꿈을 사용하여 파일 이름 생성 패턴 확장에 참여해야 합니다.

files=([^.]*(.U))
files=${(F)files}

아니면 기본적으로

files=$(find . -maxdepth 1 -type f -uid $EUID ! -name '.*' -exec basename '{}' \;)

zsh를 사용하여 직접 수행하는 방법을 알고 싶습니다. $files스키마를 한 번에 확장하고 연결된 배열을 문자열로 할당하려면 어떻게 해야 합니까 ?

와 같은 수십 가지 변형을 시도했습니다 files=${(@F)${:-[^.]*(.U:wq)}}. 나는 노력했다glob 한정자를 사용하지만 files=([^.]*(.U^P:\\n:))별도의 단어(공백 두 개, $IFS도 변경해 보았습니다)를 삽입하고 추가합니다.마지막 항목 이후. 조인 수정자가 있으면 좋을 것입니다.

내가 뭐 놓친 거 없니?

답변1

${(F)...}매개변수 확장입니다. 하지만중첩된 확장 허용,

${...}대신 유형 매개변수 표현식을 사용하거나 $(...)유형 명령 대체를 사용하는 경우이름위에서는 먼저 확장하고 그 결과를 마치 확장한 것처럼 사용합니다.이름.

중첩은 매개변수 확장 및 명령 대체로 제한됩니다. ([^.]*(.U))둘 다 아닙니다. 파일 이름 생성으로 구성된 배열 정의의 일부입니다. 이 경우 파일 이름 생성은 발생하지 않습니다. 매개변수 확장이 완료될 때까지 발생하지 않습니다(중첩된 명령 대체를 제외하고 여기서는 특별히 유용하지 않습니다). 이는 다음에서 확장됩니다.매개변수 확장 규칙:

각 중첩 대체 수준에서 대체된 단어는 명령 대체, 산술 확장 및 파일 이름 확장(예: 선행 합계 ~) 을 포함하여 모든 형태의 단일 단어 대체(즉, 파일 이름 생성 아님)를 거칩니다 =.

그렇기 때문에 이 두 가지를 함께 사용할 수는 없습니다. 다음과 같은 외부 도구에 의존하지 않고 이 작업을 수행할 수 있는 내장된 방법을 원하는 경우 find명령 대체가 여전히 방법을 제공할 수 있습니다.

files=$(print -lr -- [^.]*(.U))

답변2

추가 옵션:

  • 익명 함수를 사용하세요.

    (){ files=${(F)@}; } *(U.^D)
    
  • 사용 printf -v:

    printf -v files '%s\n' *(U.^D)
    

    (그 사람은 \n마지막에 하나가 있습니다). $files미리 배열로 선언하면 안 됩니다.

  • 전역 확장자를 직접 할당할 수는 없습니다.스칼라전역 변수가 생성되면 모든 변수가 하나로 할당됩니다.목록so는 배열 또는 연관 배열에 할당하는 데에만 적합합니다. 정말로 원하지만(왜 그렇게 하는지는 확실하지 않습니다) @Gilles가 제안한 대로 명령 대체를 사용하여 문제를 해결할 수 있습니다. 이는 서브쉘을 분기하고 모든 후행 개행 문자를 제거하는 것을 의미합니다.

    포크를 포함하지 않는 또 다른 방법은 zsh'를 사용하는 것입니다.동적으로 이름이 지정된 디렉터리함수 - 사용자 정의 확장을 생성하기 위해 사용자 정의 코드를 호출하는 방법입니다.

    zsh_directory_name_functions+=(expand-glob)
    expand-glob() {
      emulate -L zsh
      set -o extendedglob
      local match
      [[ $1 = n && $2 = (#b)glob:(*):(*) ]] && {
        local sep=$match[1]
        reply=(${~match[2]}(#qN))
        reply=(${(pj:$sep:)reply})
      }
    }
    

    그런 다음 다음을 수행하십시오.

    files=~[glob:$'\n':*(#qU.^D)]
    

하지만 이것이 당신이 원하는 것이라고 확신하나요? /이 파일을 또는 이외의 문자와 연결 하면 \0원본 파일 목록을 복원할 수 없습니다. 왜냐하면 ( /\0)만 파일 이름에 나타날 수 없는 문자이기 때문입니다.

배열에 저장하지 않는 이유:

files=(*(NU.^D))

그러면 잃을 것이 없다는 것을 알게 될 것입니다.

사용자에게 목록을 인쇄해야 하는 경우 언제든지 다음을 수행할 수 있습니다.

print -rC1 -- $files

또는 지원되는 인용 양식을 사용하여 zsh정보 손실을 방지하세요.

print -rC1 -- "${(@q+)files}" # human friendly
print -rC1 -- "${(@qq)files}" # safe for reinput to the shell or z flag

이 옵션은 전역적으로 설정하는 경우에만 필요합니다 [^.].^Ddotglob

print -C1print -lN한 열에 인쇄하는 것은 빈 인수 목록( 일치하는 파일이 없을 때 오류를 피하기 위해 ullglob glob 한정자를 사용하고 있기 때문에 여기서 발생할 수 있음)과 동일하며 여전히 빈 줄을 출력합니다.

해당 파일 목록을 파일에 저장하여 편집하고 나중에 모든 정보를 유지하면서 결과를 로드하려면 다음을 수행할 수 있습니다.

files=(*(.U^D))
printf '%q\n' $files > file

의 경우 파일 %q이름은 따옴표로 묶여 있습니다 . 예 를 들어 .zshfoo<newline>bar$'foo\nbar'

그럼 넌 할 수 있어편집된 파일을 다음과 같이 새 배열에 배치합니다.

newfiles=("${(f@Q)$(<file)}")

매개 Q변수 확장 플래그가 역참조됩니다.

그런 다음 다음을 수행하십시오.

(($#files == $#newfiles)) &&
   for old new (${files:^newfiles}) mv -i -- $old $new

관련 정보