내 디렉토리 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
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/
. 로 시작하는 파일/디렉토리 이름이 있는 경우 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/