今月のすべてのファイル+以前の最新のファイルを保持し、残りは削除します。

今月のすべてのファイル+以前の最新のファイルを保持し、残りは削除します。

現在の時刻+以前の最新ファイルと同じ月のタイムスタンプを持つすべてのファイルを保持し、ディレクトリ内の残りのファイルを削除するシェルスクリプトが必要です。

ディレクトリに保存されているすべてのファイル名は、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

PS。シェルにとても新しいものです。あなたは動作するコードが欲しいだけでなく、学ぶことができるようにしたいです。その場合はコードも説明してください。ありがとうございます!

答え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日から現在まで範囲。

関連情報