수정 시간별로 이미지를 정렬 및 필터링하고 FreeBSD의 nsxiv에서 보는 방법

수정 시간별로 이미지를 정렬 및 필터링하고 FreeBSD의 nsxiv에서 보는 방법

나는 사용하고있다nsxivFreeBSD에서 JPEG 및 PNG 이미지를 봅니다. 하지만 FreeBSD의 nsxiv에서 이미지를 보기 위해 수정 시간별로 이미지를 정렬하고 필터링하는 방법을 찾을 수 없습니다. GNU coreutils 및 GNU findutils를 사용하는 Linux에서는 다음 명령을 사용하여 2023년 10월 1일 이후에 수정된 이미지를 수정 시간별로 정렬하여 볼 수 있습니다.

find . -maxdepth 1 -type f \
    \( -iregex '.+\.jpe?g$' -o -iregex '.+\.png$' \) \
    -newermt 2023-10-01 \
    -exec ls -t --zero -- {} + | \
        nsxiv -0 -

공백, 개행 및 기타 특이한 문자가 포함된 파일 이름을 처리하는 동일한 명령을 FreeBSD에서 찾을 수 없습니다. 문제는 FreeBSD에 있습니다.lsFreeBSD의 또 다른 문제는 --zeroNUL로 구분된 파일 이름을 출력하는 옵션이 없습니다 .nsxivfind-printf0에 전달할 수 있는 항목이 없습니다 sort -z. 이미지를 수정 시간별로 정렬 및 필터링하고 FreeBSD의 nsxiv에서 보는 방법은 무엇입니까?

저는 Linux와 FreeBSD에서 /bin/sh(대시)를 사용하고 있습니다 /bin/sh.

답변1

일반 FreeBSD 시스템에서 실행하는 것이 중요하다면 find/xargs/cut/stat에 대한 또 다른 대답이 있습니다. 다른 유틸리티를 설치할 수 있는 경우 zsh를 사용하는 더 명확한 답변도 있습니다.

하지만 GNUism과 Linux에 익숙하다면 GNU가 설치되어 있으면 FreeBSD에서도 편하게 생활하기가 쉽습니다.도구 찾기.

pkg install findutils

마찬가지로 사람들은 BSD ls, grep, make, sed 및 awk에 갇혀 있습니다. 그러나 GNU 대응 제품도 쉽게 사용할 수 있습니다.,그누그렙,지메이크,게사르그리고멍하니. 가는거야모두그리고 나서핵심 도구

이들은 모두 시스템의 BSD 버전과 공존할 수 있습니다. 그런 다음 일반적으로 명령 앞에 GNU 버전의 "g" gnuls( , gfind, 및 ) gxargs를 붙입니다.gmakegsedgawk

좋아하는 Gnu 변형 앞에 접두사를 붙이는 것이 싫다면 "FreeBSD에서 GNU grep을 기본값으로 만드는 방법은 무엇입니까?"

BSD 변형에 익숙하다면 Linux에서도 사용할 수 있습니다. 바라보다bsdutils

답변2

정렬을 수행하려면 xargs를 올바르게 전달해야 합니다.

find . -maxdepth 1 -type f \
    \( -iregex '.+\.jpe?g$' -o -iregex '.+\.png$' \) \
    -newermt 2023-10-01 \
    -print0 \
    \|
      xargs -0 \
        stat -n -f '%Y %N\0' \
    \|
      sort -z \
    \|
      cut -z -d ' ' -f2-  \
    \|
      nsxiv -0 -

우리는 튜플이 있는 언어에서 일반적으로 볼 수 있는 "장식-정렬-장식 취소" 기술을 사용합니다. 여기서는 정렬 키(통계의 epoch 이후 초 %Y)를 값(파일 이름)과 공백으로 구분해야 합니다 . 그런 다음 cut돌아 왔습니다. 조금 당황 스럽습니다!

답변3

다음을 수행할 수 있습니다.

zsh +o caseglob -c '
  autoload after
  print -rN -- *.(jp(e|)g|png)(.e[after 2023-10-01]om)' | nsxiv -0 -

이식성과 안정성을 고려하면 perl아마도 최선의 방법은 다음과 같습니다.

perl -MTime::HiRes=lstat -MPOSIX -MFile::Glob=:nocase -e '
  $start = mktime(0,0,0, 1,10-1,2023-1900); # 2023-10-01
  for (<*.{jpg,jpeg,png}>) {
    push @files, [$_, $s[9]] if @s = lstat and -f _ and $s[9] >= $start;
  }
  print "$_->[0]\0" for sort {$b->[1] <=> $a->[1]} @files
  ' | nsxiv -0 -

귀하의-exec ls -t --zero -- {} +파일 목록이 너무 커서 여러 번 find호출해야 하는 경우 ls파일을 수정 시간별로 제대로 정렬할 수 없습니다.

답변4

FreeBSD에서 작동하는 솔루션을 찾았습니다 /bin/sh. FreeBSD 13.2에서 시도해 보았습니다. 선행 및 후행 공백을 포함하여 백슬래시와 공백(공백, 탭 및 줄 바꿈)이 포함된 파일 이름을 올바르게 처리하는 것으로 보입니다.

find . -maxdepth 1 -type f \
        \( -iregex '.\{1,\}\.jpe\{0,1\}g$' -o -iregex '.\{1,\}\.png$' \) \
        -newermt 2023-10-01 \
        -exec ls -l -B -D%s {} + \
    | cut -w -f6- | sort -r | cut -f2- \
    | while read -r line; do
        printf '%b\0' "$line"
      done \
    | nsxiv -0 -

작동 방식:

  • ls -l -B -D%s
    • -B인쇄할 수 없는 문자를 8진수 표기법으로 표시합니다. 이는 개행 문자와 탭이 포함된 파일 이름을 처리하는 데 중요합니다.
    • -D%s형식 파일 수정 시간(에포크 이후의 초 수)입니다. 수정 시간별로 정렬하는 데 유용합니다.
  • cut -w -f6-ls -l ...: 파일 수정 시간과 파일 이름이 포함된 열을 제외하고 출력에서 ​​모든 열을 제거합니다 . -w연속된 공백은 구분 기호로 간주되어야 합니다.
  • sort -r: 수정 시간을 기준으로 가장 최근 것부터 오래된 것 순으로 파일을 정렬합니다.
  • cut -f2-: 파일 수정 시간 열을 제거하고 (줄 바꿈으로 구분된) 파일 이름만 유지합니다.
  • 마지막 부분: 개행으로 구분된 파일 이름을 하나씩 읽고 printf형식 %b문자열을 사용하여 파일 이름의 8진수 표기법을 다시 실제 문자(예: 개행 및 탭 포함)로 변환합니다. NULL 문자( \0)를 사용하여 파일 이름을 구분하고 NULL로 구분된 파일 이름을 nsxiv -0 -.

추가 참고 사항:

  • cut -w -f6- | sort -r | cut -f2-ls대신 사용할 수 없는 옵션입니다 -t. 사용자 "Stéphane Chazelas"는 이 페이지의 다른 답변에 다음과 같이 썼습니다.

    find ... -exec ls -t ... -- {} +파일 목록이 너무 커서 여러 번 find호출해야 하는 경우 ls[ ]는 수정 시간별로 파일을 제대로 정렬할 수 없습니다.

  • find ... \( -iregex '.\{1,\}\.jpe\{0,1\}g$' -o -iregex '.\{1,\}\.png$' \)이는 확장 정규식을 사용하여 단순화할 수 있습니다. 예를 들어 find -E ... -iregex '.+\.(jpe?g|png)$'.
  • 소유자나 그룹 이름에 공백 문자가 있는 특별한 경우에는 이름 대신 사용자 ID와 그룹 ID가 출력되도록 옵션 -n을 추가해야 할 수도 있습니다.lsls

관련 정보