다음과 같은 줄 바꿈을 사용하여 파일 이름 생성 패턴 확장에 참여해야 합니다.
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
이 옵션은 전역적으로 설정하는 경우에만 필요합니다 [^.]
.^D
dotglob
print -C1
print -l
N
한 열에 인쇄하는 것은 빈 인수 목록( 일치하는 파일이 없을 때 오류를 피하기 위해 ullglob glob 한정자를 사용하고 있기 때문에 여기서 발생할 수 있음)과 동일하며 여전히 빈 줄을 출력합니다.
해당 파일 목록을 파일에 저장하여 편집하고 나중에 모든 정보를 유지하면서 결과를 로드하려면 다음을 수행할 수 있습니다.
files=(*(.U^D))
printf '%q\n' $files > file
의 경우 파일 %q
이름은 따옴표로 묶여 있습니다 . 예 를 들어 .zsh
foo<newline>bar
$'foo\nbar'
그럼 넌 할 수 있어짐편집된 파일을 다음과 같이 새 배열에 배치합니다.
newfiles=("${(f@Q)$(<file)}")
매개 Q
변수 확장 플래그가 역참조됩니다.
그런 다음 다음을 수행하십시오.
(($#files == $#newfiles)) &&
for old new (${files:^newfiles}) mv -i -- $old $new