수정 날짜별로 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}#*:})
%N
zstat 형식(나노초 해상도로 타임스탬프를 얻으려면)에는 zsh ≥5.6이 필요합니다 . zsh가 오래된 경우 이를 제거하면 코드는 계속 작동하지만 타임스탬프를 1초 단위로 비교합니다. 많은 파일 시스템에는 1초 미만의 해상도가 있지만 stat
이전 버전의 zsh에서는 zsh 모듈을 사용하여 이를 얻을 수 없을 것 같습니다 .
zsh가 너무 오래된 경우 다음 stat
유틸리티를 사용하여 더 정확한 타임스탬프를 얻을 수 있습니다.GNU 코어 유틸리티. 가지고 계시다면 아마도 다른 GNU coreutil도 가지고 계실 것이므로 저는 그것을 사용하겠습니다. GNU coreutils는 일반적으로 비임베디드 Linux에 있지만 BSD나 macOS에는 없을 수도 있습니다. macOS에서는 brew
. GNU coreutils가 기본 운영 체제의 일부가 아닌 경우 , 로 변경 해야 할 stat
수도 있습니다 .gstat
sort
gsort
cut
gcut
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 전용이기 때문입니다.)