用于模式匹配和删除文件的bash脚本

用于模式匹配和删除文件的bash脚本,bash,shell,Bash,Shell,问题:在目录中,我有以下格式的文件: <account-number>-<invoice-number>, an example being: 123456-3456789 123456-6789023 123456-2568907 ... 456789-2347890 456789-2344357 etc. 我想做的是,如果同一个帐户有多个发票,请删除除最新发票之外的所有发票。如果只有一个,别管它 感谢您的指点。您可以使用此基于awk的脚本: mkdir _tmp

问题:在目录中,我有以下格式的文件:

<account-number>-<invoice-number>, an example being:

123456-3456789
123456-6789023
123456-2568907
...
456789-2347890
456789-2344357

etc.
我想做的是,如果同一个帐户有多个发票,请删除除最新发票之外的所有发票。如果只有一个,别管它


感谢您的指点。

您可以使用此基于awk的脚本:

mkdir _tmp
ls -rt *-*|awk -F'-' '{a[$1]=$0} END{for (i in a) system("mv " a[i] " _tmp/")}'

一旦您对中的文件感到满意。/\u tmp/从当前目录中删除所有文件并将文件移到另一个目录。

这里有一个纯bash解决方案,在验证echo时将其替换为rm

for file1 in *-*
do 
    IFS=- arr=($file1)
    for file2 in "${arr[0]}"*
    do 
        [ "$file1" -nt "$file2" ] && echo "$file2"
    done
done
Bash中的一个不错的例子: 伪就地处理

#!/bin/bash -e

ADIR="/path/to/account/directory"
TMP="$ADIR.tmp"

mkdir "$TMP" && rmdir "$TMP" && mv "$ADIR" "$TMP" && mkdir "$ADIR"

while IFS=- read ACCNT INVOICE < <( ls -t1 "$TMP" )
do
    mv "$TMP/$ACCNT-$INVOICE" "$ADIR/$ACCNT-$INVOICE" && rm "$TMP/$ACCNT"*
done

rmdir "$ADIR.tmp"
它的作用是:

1首先将帐户目录移动到临时目录。是原子的 2在循环中:列出最新发票,将其移动到新目录,删除具有相同帐户的发票。 3删除临时目录

优点: 可靠、安全、简短、速度合理,并在出现严重错误时停止

缺点: 非常明确,确保始终有备份

评论: 您可能已经注意到mkdir$TMP&&rmdir$TMP 这是故意的:rmdir为dir not exist提供与dir not empty相同的返回值 因此,与其检查两者中的哪一个 [-d$DIRNAME]&&&{rmdir$DIRNAME | | exit} 我使用了上面的结构

此外,ls-t1$TMP可能是在一个陌生的地方乍一看
但是没关系,每次迭代都会再次执行,但只读取第一行

您如何判断帐号是什么?在-?是之前,对于123456-3456789,123456是账号,3456789是发票号。所以在上面的例子中,如果123456-3456789是最新的,我想删除以123456等开头的另外两个。最新的发票是由时间戳或发票号决定的?Anubhava的解决方案对您不起作用还是您想要更优雅的阅读一行?不起作用。所有最新的文件都没有移到tmp。对不起,我没有看到时间戳检查?太棒了!非常感谢。