가장 오래된 파일을 한 디렉토리에서 다른 디렉토리로 이동하는 쉘 스크립트

가장 오래된 파일을 한 디렉토리에서 다른 디렉토리로 이동하는 쉘 스크립트

저는 쉘 스크립팅을 처음 접했습니다. 나는 해결책을 찾고 있습니다. 디렉토리에 파일이 추가되는 경우를 대비하여 내 디렉토리에 10개의 파일을 유지해야 합니다. 가장 오래된 파일만 다른 디렉토리로 옮기고 싶습니다. 내 디렉터리 이름은 Work로 지정하고 다른 디렉터리 이름은 Regular_archieve로 지정했습니다. 나는 이것을 시도했다.

work = /home/balaji/work
regular_archieve = /home/balaji/regular_archieve
cd $work
for i in 'ls -t | sed -e '1,10d' | xargs -d '\n' rm -f'
do
 mv $i $regular_archieve
done
if [ls -t | wc -1 > 10 | mv /home/balaji/regular-archieve]
 then
   echo "more than 10 n files"
fi
mv $(ls -t /home/balaji/work | sed -e '1,10d' | tail - 1) /home/balaji/regular_archieve

하지만 파일을 다른 디렉토리로 이동할 수는 없습니다.

이 오류가 발생합니다.

mv: cannot stat 'file' : No such file or directory

답변1

ls터미널에서 보는 것 이외의 용도로 의 출력을 사용하는 것은 좋지 않습니다. 바라보다아니요구문 분석 ls(및 수행 방법)?. 대신 다음을 사용하십시오 find.

find /home/balaji/work/ -type f -printf '%C@\t%p\0' |
  sort -z -k1,1 -r -n |
  cut -z -f2 |
  head -z -n 10 | 
  xargs -0r echo mv -t /home/balaji/regular_archive/

find이를 위해서는 GNU 버전의 , sort, 및 (또는 최소한 NUL 레코드 구분 기호 옵션을 지원하는 다른 버전) cut이 필요합니다.tailxargs-z

  • find모든 일반 파일에 대해 -printf '%C@\t%p\0'마지막으로 변경된 타임스탬프( %C@1970-01-01 00:00:00 이후의 초 수) 및 파일 이름( )을 나열하는 데 사용됩니다. 필드는 단일 탭 문자( )로 구분되며 각 레코드는 %pNUL 문자( )로 \t구분됩니다 .\0
  • find의 출력은 -r첫 번째 필드( )에 대해서만 파일을 숫자 역순( )으로 정렬하기 위해 sort로 파이프됩니다. 즉, 타임스탬프를 기준으로 합니다.-n-k 1,1
  • 정렬의 출력은 타임스탬프 필드를 제거하기 위해 파이프로 연결됩니다(정렬이 완료된 후에는 더 이상 필요하지 않음).
  • cut의 출력은 head처음 10개 항목을 얻기 위해 파이프로 연결됩니다.
  • 마지막으로 head의 출력이 xargsrun mv명령으로 파이프됩니다. 이는 mv의 GNU -t확장자를 사용하므로 파일 이름 앞에 대상 디렉터리를 지정할 수 있습니다.

사실 이건 run 이라기 echo mv보다는 run mv이기 때문에 pre-run 입니다. echo그것이 당신이 원하는 것을 할 것이라는 확신이 들면, 그것을 제거하십시오.

참고: 이는 다음에 적용됩니다.어느포함되어 있을 수 있는 이상하고 성가신 문자(예: 공백, 줄 바꿈, 셸 메타 문자 등)에 관계없이 파일 이름입니다. 또한 이 file명령에는 검색 기준을 구체화하는 데 사용할 수 있는 다른 많은 옵션이 있습니다.


이전 버전의 GNU coreutils(예: < 버전 8.25)를 사용하는 경우 cut에도 옵션이 없습니다head . 대신 이것을 사용할 수 있습니다 . 예를 들어tail-zawk

find /home/balaji/work/ -type f -printf '%C@\t%p\0' |
  sort -z -k1,1 -r -n |
  awk -F '\t' 'BEGIN {RS=ORS="\0"}; NR<=10 { $1=""; $0=$0; $1=$1 ; print }' |
  xargs -0r echo mv -t /home/balaji/regular_archive/

perl또는 다음을 대신 사용할 수 있습니다 awk.

 perl -F'\t' -0lane 'if ($. <= 10) {delete $F[0]; print @F}'

답변2

나는 귀하의 코드에서 명백한 구문 오류를 무시하고 가장 최근에 수정된 10개의 파일을 디렉토리에 보관하기를 원한다고 가정합니다 ~/work. 또한 zsh사용 가능한 쉘이 있다고 가정합니다 .

다음 쉘 스크립트는 zsh가장 최근에 수정된 10개의 파일을 제외한 모든 파일을 에서 ~/work로 이동합니다 ~/regular_archieve.

#!/bin/zsh

mv -i $HOME/work/*(.om[11,-1]) $HOME/regular_archieve

스크립트의 단일 명령은 가장 최근에 수정된 10개의 파일을 에 보관 ~/work하고 나머지 파일을 ~/regular_archieve. 특정 와일드카드 패턴을 mv사용하여 이를 수행합니다 zsh. 패턴은 *(.om[11,-1])이동해야 하는 일반 파일로 확장됩니다(디렉토리가 일치하지 않음). om수정 타임스탬프를 기준으로 파일을 정렬하고 이 [11,-1]정렬된 목록의 파일 이름 11에서 가장 오래된 파일을 선택합니다. 출발점글로벌 예선 .om[11,-1]glob이 일반 파일에만 일치하도록 만듭니다.

디렉터리에 수천 개의 파일이 있는 경우 "매개변수 목록이 너무 김" 오류가 생성될 수 있습니다. 이 경우 루프를 사용하여 파일을 개별적으로 이동합니다.

#!/bin/zsh

for pathname in $HOME/work/*(.om[11,-1]); do
    mv -i $pathname $HOME/regular_archieve
done

답변3

이 질문에 대한 또 다른 답을 찾았습니다. 사용하기 가장 좋습니다찾다사용하는 대신 명령엘에스주문하다. 이렇게 하면 가장 오래된 파일을 찾아 사용할 수 있게 됩니다.MV다른 디렉터리로 이동하는 명령입니다.

mv $(find /home/balaji/work/ -type f -printf '%T+ %p\n' | sort | head -1) /home/balaji/regular_archieve

find– 디렉터리 계층 구조에서 파일을 검색합니다.

/home/balaji/work/– 위치를 검색합니다.

/home/balaji/regular_archieve/- 목표 위치.

type -f– 일반 파일만 검색합니다.

-printf ‘%T+ %p\n’– 파일의 마지막 수정 날짜와 시간을 + 기호로 구분하여 인쇄합니다. (예: 2015-07-22+13:42:40.0000000000). 여기서 %p는 파일 이름을 나타냅니다. \n은 줄 바꿈을 의미합니다.

sort | head -n 1– sort 명령은 출력을 정렬하고 출력을 head 명령으로 보내 가장 오래된 파일을 표시합니다. 여기서 -n 1은 가장 오래된 파일인 단 하나의 파일만 있음을 의미합니다.

관련 정보