디렉토리에서 폴더에서 가장 오래된 파일을 선택하는 방법

디렉토리에서 폴더에서 가장 오래된 파일을 선택하는 방법

내 디렉토리 n에 파일이 많이 있습니다 . ../in/해당 파일 중에서 가장 오래된 파일을 처리하여 디렉토리로 보내길 원합니다 ../complete/. 나머지 파일은 디렉터리로 전송됩니다 ../error/. 누구든지 도와줄 수 있나요?

답변1

가장 오래된 파일을 다음 위치에 복사하려면 ../complete:

cp -v "$(find ../in -maxdepth 1 -type f -printf '%T@ %p\0' | sort -zn | \
  sed -zn '1s/[0-9,\.]\+ //p')" ../complete

가장 오래된 것을 제외한 모든 것을 복사하려면 다음을 수행하십시오 ../error.

find ../in -maxdepth 1 -type f -printf '%T@ %p\0' | sort -zn | \
  sed -zn '2,$s/[0-9,\.]\+ //p' | xargs -0 cp -vt ../error

설명:

  • find
    • -maxdepth 11레벨만 내려갑니다. 따라서 디렉토리를 재귀적으로 검색하지 않습니다.
    • -type f파일만 일치합니다.
    • -printf '...'사용자 정의 출력 형식. %T@파일의 마지막 수정 시간을 타임스탬프로 제공하며 %p파일 이름입니다. \0결국 주목하십시오 . 파일은 개행으로 구분되지 않고 널 바이트로 구분되어 인쇄됩니다. 왜냐하면 개행은 아마도 파일 이름의 문자일 수 있고 이로 인해 명령이 중단될 수 있기 때문입니다.
  • sort -zn이렇게 하면 구분된( ) 출력 널 바이트를 읽고 -z숫자로 정렬( -n)합니다.
  • sed -zn구분된 출력 널 바이트를 읽습니다.
    • 1첫 번째 줄(첫 번째 명령)만 일치하고 2,$다른 모든 줄(두 번째 명령)과 일치합니다.
    • s/[0-9,\.]\+ //p출력에서 선행 타임스탬프를 제거합니다.
  • 두 번째 명령에서만: 구분된 널 바이트( ) xargs -0 cp -vt ../error로 구분된 출력을 처리 하고 파일을 복사하는 모든 입력을 호출합니다.-0cp -vt ../error

예제 출력:

$ ls -lt ../in/
total 0
-rw-r--r-- 1 user user 0 Jun 24 08:18 file2
-rw-r--r-- 1 user user 0 Jun 24 08:18 file3
-rw-r--r-- 1 user user 0 Jun 24 08:18 file4
-rw-r--r-- 1 user user 0 Jun 24 08:18 file5
-rw-r--r-- 1 user user 0 Jun 24 08:17 file_oldest
$ cp -v "$(...)" ../complete
'../in/file_oldest' -> '../complete/file_oldest'
$
$ find ... | xargs ... ../error
'../in/file2' -> '../error/file2'
'../in/file3' -> '../error/file3'
'../in/file4' -> '../error/file4'
'../in/file5' -> '../error/file5'

답변2

가장 오래된 파일을 찾아 원하는 디렉터리로 이동하려면 다음을 사용하세요.

# cd to ../in/

$ ls -lt | grep -v '^d' | tail -1 | awk '{print $NF}' | xargs -I '{}' mv '{}' ../complete/

이제 가장 오래된 파일이 외부로 이동되었으므로 모든 파일을 다음으로 이동할 수 있습니다.../error/

$ mv -- * ../error/

. 로 시작하는 파일/디렉토리 이름이 있는 경우 after가 필요 합니다 --.mv-

답변3

구축라훌의 대답:

$ ls -ltr | grep -v '^d' | awk 'NR==2 {print $NF; exit}' | xargs -I '{}' mv -- '{}' ../complete/

노트:

  • 당신은 "가장 오래된 파일"로 뭔가를 하고 싶다고 말했습니다. 모든 답변은 최근에 가장 적게 수정되었음을 의미한다고 가정합니다. 가장 최근에 말했다면변경됨, 그렇게 말하세요; 대답은 약간 다를 것입니다. 가장 최근에 말했다면만들어진, 당신이 원하는 것은 Unix에서는 거의 불가능합니다.
  • ls -lt(Rahul이 사용한 것)은 수정 날짜/시간순으로 최신 디렉토리와 가장 오래된 마지막 디렉토리를 포함하여 긴 형식으로 현재 디렉토리를 나열합니다.  ls -ltr아르 자형그 반대; 가장 오래된 것이 먼저이고 최신이 마지막이 됩니다.
  • 이름이 마침표(.) A에 옵션을 추가합니다 ls. 예: ls -ltrA. (옵션의 순서는 중요하지 않습니다. , 또는 원하는 경우에도 사용할 수 ls -ltAr있습니다 ls -lAtr. ls -ltr -A)
  • 나는 거짓말했다. 긴 ls디렉토리 목록에는 항상 total첫 번째 줄이 있습니다. 에서는 ls -ltr가장 오래된 항목이두번째선.
  • grep -v '^d'디렉터리를 필터링합니다(있는 경우).
  • awk 'NR==2 { print $NF; exit }' 두 번째 줄(가장 오래된 파일)부터 마지막 ​​필드(파일 이름*)를 인쇄한 후 종료됩니다.

    • 이는 에 비해 프로세스가 하나 적습니다 tail -1 | awk '{print $NF}'.
    • awk종료할 때 이 ls종료될 수 있고 전체 디렉토리에 대한 목록이 생성되지 않으므로 이 방법이 더 빠르게 작동할 수 있습니다 .
    • grep다음을 수행하여 제거할 수 있습니다.

      ls -ltr | awk '! /^d/ { count++ } count==2 { print $NF; exit }'
      

      하지만 나는 그것을 조언하지 않을 것입니다. 지나치게 복잡한 스크립트는 유지 관리가 어렵습니다.

  • 이후--mv xargs명령 에서로 시작하는 파일 이름이 있는 경우 필요합니다.-.
  • . xargs​위 명령을 다음과 같이 단순화할 수 있습니다.

    $ mv -- $(ls -ltr | grep -v '^d' | awk 'NR==2 { print $NF; exit }') ../complete/
    

________
* Rahul의 답변과 마찬가지로 파일 이름에 공백이나 탭이 포함되어 있으면 실패하며 줄 바꿈이 포함되어 있으면 더 나쁩니다.

이름이 마침표(.), shopt -s dotglob그 일을 하기 전에 해야 할 일

$ mv -- * ../error/

관련 정보