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

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

내 디렉토리에 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 1한 레벨만 내려가므로 디렉토리를 반복적으로 검색하지 않습니다.
    • -type f파일만 일치합니다.
    • -printf '...'사용자 정의 출력 형식. %T@파일의 마지막 수정 시간(타임스탬프)을 제공하며 %p파일 이름입니다. \0끝까지 주의하세요 . 파일은 줄 바꿈이 아닌 널 바이트로 구분되어 인쇄됩니다. 줄 바꿈이 파일 이름의 문자일 수 있어 명령이 중단될 수 있기 때문입니다.
  • sort -zn그러면 널 바이트로 구분된 출력을 읽고( ) -z숫자로 정렬합니다( -n).
  • sed -zn널 바이트로 구분된 출력을 읽습니다.
    • 1첫 번째 줄(첫 번째 명령)만 일치하고 2,$다른 모든 줄(두 번째 명령)과 일치 합니다.
    • s/[0-9,\.]\+ //p선행 타임스탬프가 출력에서 ​​제거됩니다.
  • 두 번째 명령에서만: xargs -0 cp -vt ../error널 바이트로 구분된( ) 출력을 처리 -0하고 cp -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/

에 대해 궁금한 점이 있으시면 --.mv-

답변3

확립된라훌의 대답:

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

노트:

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

    • 프로세스가 하나 줄어듭니다 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/

관련 정보