Bash 按关键字组分隔文件列表,然后按反向日期对每个组进行排序

Bash 按关键字组分隔文件列表,然后按反向日期对每个组进行排序,bash,sh,ls,Bash,Sh,Ls,我用这个: for f in $( ls -tr ${repSource}*.txt ); …在文件列表上循环,将最旧的文件排序为最新的文件 我想添加另一个排序“过滤器”:不以“abc”开头的文件名放在第一位,不管它们的时间戳是什么 因此,如果文件是“abc.txt”、“def.txt”和“ghi.txt”,那么“abc.txt”必须是最后一个,其他两个在列表的前面(按反向日期排序)。文件: ls -log total 12 -rw-rw-r-- 1 4 Apr 8 11:15 abc.tx

我用这个:

for f in $( ls -tr ${repSource}*.txt );
…在文件列表上循环,将最旧的文件排序为最新的文件

我想添加另一个排序“过滤器”:不以“abc”开头的文件名放在第一位,不管它们的时间戳是什么

因此,如果文件是“abc.txt”、“def.txt”和“ghi.txt”,那么“abc.txt”必须是最后一个,其他两个在列表的前面(按反向日期排序)。

文件:

ls -log
total 12
-rw-rw-r-- 1 4 Apr  8 11:15 abc.txt
-rw-rw-r-- 1 4 Apr  8 11:15 def.txt
-rw-rw-r-- 1 4 Apr  8 11:16 ghi.txt
这似乎有效,但必须有更好的方法:

ls -log --time-style +%s | tail -n +2 | \
pee \
    'grep -v abc.txt | sort -k4 -rn' \
    'grep    abc.txt | sort -k4 -rn' | \
cut -d " " -f 5
输出:

ghi.txt
def.txt
abc.txt
注意:不恰当地命名的utilpee来自debian的moreutils包,它是一个“类似于管道的tee

现在让我们来做一个循环:

# usage: foo filename   # filter above sort code by filename
foo() { ls -log --time-style +%s | tail -n +2 | \
        pee 'grep -v '"$1"' | sort -k4 -rn' \
            'grep '"$1"' | sort -k4 -rn' | \
        cut -d " " -f 5 ; }


for f in $( foo abc.txt )

您不想解析
ls
命令的输出。你问题中的结构是一个经典,众所周知是有问题的

您可以改为使用
stat
获取在模式扩展的
for
循环中找到的每个文件的时间

#!/usr/bin/env bash

uname_s=$(uname -s)

stamp() {
    case "$uname_s" in
        Linux)       stat -c '%Y' "$1" ;;
        Darwin|*BSD) stat -f '%m' "$1" ;;
    esac
}

inputfiles=( "$@" )

for file in "${inputfiles[@]}"; do
    n=$(stamp "$file")
    while [ -n "${forward[$n]}" ]; do
        ((n++))       # introduce fudge to avoid timestamp collissions
    done
    forward[$n]="$file"
done

declare -p inputfiles

for n in "${!forward[@]}"; do
        reverse[$(( 2**32 - $n ))]="${forward[$n]}"
done

declare -p forward reverse
此示例脚本将文件列表作为命令行选项(可以是glob),然后使用
declare-p
显示原始列表、正向排序列表和反向排序列表

stamp
函数中的
case
语句使它可以在Linux、OS X(Darwin)、FreeBSD、NetBSD等之间移植,因为我不知道您使用的是什么操作系统。(如果它不太常见,如Solaris、HP/UX等,则
stat
命令可能不可用或不有用,并且此解决方案可能无法工作。)

在bash中拥有排序(非关联)数组后,可以使用以下结构逐个处理文件:

for file in "${forward[@]}"; do
    # something to $file
done

您可以相信,由于非关联bash数组始终是按数字顺序排列的,因此您将按文件的日期顺序获取文件


当然,如果您愿意,您可以将日期本身作为索引。:)

使用
find
stat
来输出文件的属性,然后在这些字段上使用
sort
我使用find/stat在网络上搜索示例,然后进行排序,我想我了解它的工作原理,我会尝试!ThanksI尝试了$(ls-tr${repSource}*.txt | find.-type f-name“$masque*”| sort),但我认为“find”过滤器用于以“$masque”开头的文件。我并不真的想“过滤”,但我想对符合我条件的文件进行优先级排序。更详细地说,另一个例子,我在第一个例子中不清楚:我的存储库中有3个文件,分别是“abc.txt”、“def.txt”和“ghi.txt”,我想指定我的“for”循环读取第一个文件,它不以“abc”开头,所以我希望它在最后一个位置读取“abc.txt”。简而言之,我想读取存储库中的每个文件,但首先读取的文件不是以“abc”开头的,例如。或者读取以“abc”开头的最后一个文件,这是相同的想法。提前感谢查看此列表中的第一项:
for file in "${reverse[@]}"; do
    # something to $file
done