이번 달의 모든 파일 + 이전의 최신 파일을 유지하고 나머지는 삭제합니다.

이번 달의 모든 파일 + 이전의 최신 파일을 유지하고 나머지는 삭제합니다.

현재 시간 + 그 이전의 최신 파일과 같은 달의 타임스탬프가 있는 모든 파일을 유지하고 디렉터리의 나머지 파일을 삭제하는 쉘 스크립트를 원합니다.

디렉토리에 저장된 모든 파일 이름은 name$timestamp.extension다음과 같이 구성됩니다.

timestamp=`date "+%Y%m%d-%H%M%S"`

즉, 디렉터리에 다음 파일이 있는 경우를 의미합니다.

name161214-082211.gz
name161202-082211.gz
name161020-082211.gz
name161003-082211.gz
name161001-082211.gz

이 코드를 실행한 후 디렉터리에 남아 있는 파일은 다음과 같습니다.

name161214-082211.gz
name161202-082211.gz
name161020-082211.gz

추신. 쉘에 아주 새로운 것입니다. 당신은 작동하는 코드를 원할 뿐만 아니라 배울 수 있기를 원합니다. 그렇다면 코드도 설명해 주세요. 감사합니다!

답변1

너랑 zsh비슷한 걸 할 수 있어

# get current date (YYMM) in a variable 
crd=$(date "+%y%m")
# use a function to extract the 13 chars that make up the timestamp
dtts() REPLY=${${REPLY%%.*}: -13}
# sort file names by the timestamp in descending order, exclude the ones with the
# same YYMM as the current date and set the remaining file names as arguments
set -- *(.O+dtts^e_'[[ "${${REPLY%%.*}: -13:4}" == "$crd" ]]'_)
# remove the first item from the list (i.e. the last one before current month)
shift
# print the remaining file names
print -rl -- "$@"

이는 매개변수 확장을 사용하고글로벌 예선: 먼저 타임스탬프를 기준으로 내림차순으로 정렬된 함수(.)를 사용하여 일반 파일을 선택한 다음
, 타임스탬프가 현재 연도 및 월과 일치하면(즉, 따옴표 안의 표현식이 true를 반환하는 경우) 부정 문자열이 파일을 선택 취소합니다. 목록에서 첫 번째 항목을 제거하고(이름은 내림차순으로 정렬되므로 이는 이번 달 이전의 최신 타임스탬프가 됩니다) 결과가 만족스러우면 로 바꾸세요.Odttse^e_'[[ "${${REPLY%%.*}: -13:4}" == "$crd" ]]'_shift
print -rlrm

답변2

배쉬 솔루션은 다음과 같습니다

#!/bin/bash

keep=$(date '+%y%m')
rm `find . -name "name*" -and -not -name "name$keep*" | sort | head -n-1`
  • $keep 변수를 현재 연도(2자리)와 월로 설정합니다.
  • 백틱으로 묶인 코드를 제거한 결과는 다음과 같습니다.
    1. 현재 디렉터리(및 하위 디렉터리)에서 "name"으로 시작하고 "name$keep"으로 시작하지 않는 모든 파일 이름을 찾습니다.
    1. 결과 정렬
    1. 마지막 줄 삭제

그러나 이 경우에는 코드가 매우 빨리 복잡해지고 유지 관리가 어려워질 수 있으므로 순수 셸 스크립트를 사용하지 않습니다.

대신 Perl(또는 Python)을 사용할 수 있습니다.

#!/usr/bin/env perl

use strict;
use warnings;
use POSIX qw(strftime);

# collect the names of all files older than current month.
# we assume that there are no files from future.
my $keep_date = strftime("%y%m", localtime);
my @files = sort grep {!/^name$keep_date/} glob "*.gz";

# the newest file from the collected files shall not be deleted
pop @files; 

# delete all collected files
map {unlink} @files;

또는 명령줄에서 직접:

perl -We 'use POSIX qw(strftime); my $keep_date = strftime("%y%m", localtime); my @files = sort grep {!/^name$keep/} glob "*.gz"; pop @files; map {unlink} @files;'

답변3

또 다른 zsh방법:

# today as YYMMDD using prompt expansion
now=${(%):-%D{%y%m%d}}

# construct patterns
month="name<$now[1,4]01-$now>-<->.gz" all="name<-$now>-<->.gz"

# perform globbing (expand patterns to list of matching files)
month=($~month(N))                    all=($~all)
() (rm -f -- $argv[1,-2]) ${all:|month}

${all:|month}이는 배열 빼기를 사용하여 수행됩니다 . 여기서 $all배열은 파일 목록에서 구성됩니다.지금까지 어떤 날짜에도$month파일 목록에서 범위 및 빌드매월 1일부터 현재까지범위.

관련 정보