수정 날짜별로 zsh 배열을 정렬하는 방법은 무엇입니까?

수정 날짜별로 zsh 배열을 정렬하는 방법은 무엇입니까?

수정 날짜별로 zsh 배열을 정렬하는 방법은 무엇입니까?

files=( ~/a ~/b ~/c )
# how to sort files by date?

추신: 내 정확한 사용 사례는 다음과 같습니다. ( fz거의 fzf)

v () {
 local files
 files=() 
 command rg '^>' ~/.viminfo | cut -c3- | while read line
 do
  [ -f "${line/\~/$HOME}" ] && files+="$line" 
 done
 test -f ~/.emacs.d/.cache/recentf && {
  command rg --only-matching --replace '$1' '^\s*"(.*)"$' ~/.emacs.d/.cache/recentf | while read line
  do
   [ -f "$line" ] && files+="$line" 
  done
 }
 files="$(<<<"${(F)files}" fz --print0 --query "$*")"  || return 1
 files="${files//\~/$HOME}" 
 local ve="$ve" 
 test -z "$ve" && ! isSSH && ve=nvim 
 "${ve:-vim}" -p ${(0@)files}
 : '-o opens in split view, -p in tabs. Use gt, gT, <num>gt to navigate tabs.'
}

답변1

목록을 만들 때 목록을 정렬하면 훨씬 쉽습니다.. 하지만 그렇게 할 수 없다면…

전통적인 접근 방식은 데이터에 정렬 기준을 추가한 다음 이를 정렬하고 추가된 불필요한 부분을 제거하는 것입니다. 명확하고 사전순으로 정렬할 수 있는 형식의 타임스탬프를 사용하여 타임스탬프와 파일 이름을 포함하는 배열을 만듭니다. 배열을 정렬합니다(o 매개변수 확장 플래그), 접두사를 제거합니다. 당신은 사용할 수 있습니다stat파일의 수정 시간을 얻기 위한 모듈입니다.

zmodload zsh/stat
for ((i=1; i<$#files; i++)); do times[$i]=$(stat -g -F %020s%N +mtime -L -- $files[$i]):$files[$i]; done
sorted=(${${(o)times}#*:})

%Nzstat 형식(나노초 해상도로 타임스탬프를 얻으려면)에는 zsh ≥5.6이 필요합니다 . zsh가 오래된 경우 이를 제거하면 코드는 계속 작동하지만 타임스탬프를 1초 단위로 비교합니다. 많은 파일 시스템에는 1초 미만의 해상도가 있지만 stat이전 버전의 zsh에서는 zsh 모듈을 사용하여 이를 얻을 수 없을 것 같습니다 .

zsh가 너무 오래된 경우 다음 stat유틸리티를 사용하여 더 정확한 타임스탬프를 얻을 수 있습니다.GNU 코어 유틸리티. 가지고 계시다면 아마도 다른 GNU coreutil도 가지고 계실 것이므로 저는 그것을 사용하겠습니다. GNU coreutils는 일반적으로 비임베디드 Linux에 있지만 BSD나 macOS에는 없을 수도 있습니다. macOS에서는 brew. GNU coreutils가 기본 운영 체제의 일부가 아닌 경우 , 로 변경 해야 할 stat수도 있습니다 .gstatsortgsortcutgcut

if (($#files)); then
  sorted=(${(0@)"$(stat  --printf='%040.18Y:%n\0' "$files[@]" | sort -rz | cut -z -d':' -f2-)"})
else
  sorted=()
fi

대안적인 zsh 접근 방식은 모든 파일 $files과 그 이상을 포함하는 패턴을 구축하는 것입니다. 이 패턴과 일치하는 파일을 정렬한 다음 원하는 파일만 포함하도록 필터링합니다. 에 대한 전체 패턴을 구축해야 하는데 more_files, 이는 항상 실용적이지 않을 수 있습니다.

more_files=(~/*(Om))
sorted=(${more_files:*files})

답변2

다음과 유사한 접근 방식을 사용할 수 있습니다.하나:

zmodload zsh/stat

array=(file1 file2...)

# store mtimes in an associative array:
typeset -A mtime
stat -nLF %s.%N -A mtime +mtime -- $array

# sort using the Oe glob qualifier
sorted_array=(/(e['reply=($array)']nOe['REPLY=$mtime[$REPLY]'])

( %N나노초에는 zsh 5.6 이상이 필요합니다).

답변3

Jeff가 지적했듯이 다음과 같이 정렬된 배열을 만드는 것이 더 쉬울 것입니다.

set -A files $(ls -trd -- ~/a ~/b ~/c)

ls여기서는 문자 의 출력을 분할합니다 $IFS(기본적으로 SPC, TAB, LF 및 NUL 포함). LF에서만 분할하려면(SPC 또는 TAB 문자가 포함된 파일 이름으로 작업할 수 있지만(물론 LF는 아님)) 매개변수 확장 플래그를 설정 IFS=$'\n'하거나 사용할 수 있습니다.f

files=(${(f)"$(ls -trd -- $files)"})

array=(...)(여기서는 ksh88 스타일 대신 zsh 스타일 구문을 사용합니다. set -A array ...왜냐하면 해당 구문은 이미 zsh 전용이기 때문입니다.)

관련 정보