수정된 날짜별로 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}#*:})

zstat 형식 %N(나노초 해상도로 타임스탬프 가져오기)에는 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

$files또 다른 zsh 접근 방식은 모든 파일 등을 포함하는 스키마를 구축하는 것입니다 . 이 패턴과 일치하는 파일을 정렬한 다음 필요한 파일만 포함하도록 필터링합니다. 실제로 전체 스키마를 구축해야 하는데 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 전용이기 때문입니다.)

관련 정보