2

私はシェルスクリプトを初めて使用し、シェルスクリプトを使用してディレクトリから最新のファイルを選択する必要があります

ディレクトリ名: FTPDIR

このディレクトリのファイルは

APC5502015VP072020121826.csv
APC5502015VP082020122314.csv
APC5502015VP092020121451.csv
CBC5502015VP092020122045.csv
CBC5502015VP102020122045.csv
S5502015VP072020121620.csv
S5502015VP072020122314.csv
S5502015VP092020122045.csv

注: (各グループから最新のものを 1 つ選択する必要があります)- 以下は、シェル スクリプトを実行した後に取得する必要がある出力です。

APC5502015VP092020121451.csv
CBC5502015VP102020122045.csv
S5502015VP092020122045.csv

例: 最新のファイルAPC5502015VP092020121451.csvでは、no 092020121451 は形式の日付部分でありMMDDYYYYHHMM 、文字列部分は APC5502015VP (文字列部分の長さは固定されていません) です。

シェル スクリプトを使用してディレクトリからこれら 3 つのファイルを選択する必要があります。

これを解決するのを手伝ってもらえますか?

4

3 に答える 3

2

これを bash だけで安全に行うのは非常に困難です。Jonathan が述べたように、スペースや改行などの「特殊な」文字はスクリプトを台無しにする可能性があります。

それらのいずれもないと想定できる場合、他のツールを使用せずに、ほとんどの作業を bash で実行できます。

# Make an associative array to record types, in the second loop...
declare -A a

for file in *.csv; do
    # First, we convert the filenames into something that can be sorted.
    # The next three lines account for your "unknown length" in the first part
    # of the filename. We assume the date+time is the 12 chars before ".csv".
    new="$(rev <<<"$file")"
    new="${new:4:12}"
    new="$(rev <<<"$new")"
    new="${new:4:4}${new:0:2}${new:2:2}${new:8:4}"
    len=$(( ${#file} - 16 ))
    echo "$new ${file:0:$len} $file"
done | sort | while read date type file; do
    # Next, we print only the first of each "type"...
    if [[ ${a[$type]} -eq 0 ]]; then
        a[$type]=1
        echo "$file"
    fi
    # And stop once we have collected three types.
    if [[ ${#a[*]} -ge 3 ]]; then
        break
    fi
done

私が言うように、これはファイル名の改行を処理しません。

これはbash に組み込まれていないrevandを使用することにも注意してください。sortこれらのrev部分は、より多くのコードを使用して内部的に実行できます。これにより、実行速度が向上する可能性がありますが、非常に極端な場合にのみ違いが見られます。sortbash には が組み込まれていないため、についてできることはあまりありません。

于 2012-11-22T00:20:43.967 に答える
1

この Perl スクリプトは、指定されたデータに対して機能します。改善できることは間違いありません。

#!/usr/bin/env perl
use strict;
use warnings;

my %bases;

while (<>)
{
    chomp;
    my $name = $_;
    my($prefix, $mmdd, $yyyy, $hhmm) = ($name =~ m/(.*)(\d{4})(\d{4})(\d{4})\.csv/);
    #print "$name = $prefix $yyyy $mmdd $hhmm\n";
    my $stamp = "$yyyy$mmdd$hhmm";
    if (!exists($bases{$prefix}) || ($stamp > $bases{$prefix}->{stamp}))
    {
        $bases{$prefix} = { name => $name, stamp => $stamp };
    }
}

foreach my $prefix (sort keys %bases)
{
    print "$bases{$prefix}->{name}\n";
}

出力:

APC5502015VP092020121451.csv
CBC5502015VP102020122045.csv
S5502015VP092020122045.csv
于 2012-11-20T08:38:45.270 に答える
0

これはawkソリューションです:

cd FTPDIR
ls -1|awk -F"VP" '{split($2,a,".");if(a[1]>b[$1]){b[$1]=$2}}END{for(i in b)print i"VP"b[i]}'

以下でテスト済み:

> cat temp
APC5502015VP072020121826.csv
APC5502015VP082020122314.csv
APC5502015VP092020121451.csv
CBC5502015VP092020122045.csv
CBC5502015VP102020122045.csv
S5502015VP072020121620.csv
S5502015VP072020122314.csv
S5502015VP092020122045.csv
> awk -F"VP" '{split($2,a,".");if(a[1]>b[$1]){b[$1]=$2}}END{for(i in b)print i"VP"b[i]}' temp
CBC5502015VP102020122045.csv
S5502015VP092020122045.csv
APC5502015VP092020121451.csv
于 2012-11-20T09:32:35.957 に答える