【问题标题】:Search for similar duplicate filenames (differs the datestamp at end of filename)搜索相似的重复文件名(文件名末尾的日期戳不同)
【发布时间】:2016-02-01 14:14:45
【问题描述】:

我有一个类似(几乎相同)的问题,例如 (Keep latest file and delete all other) 除了我的文件列表不同而且我不懂 Python(试图在 Bash 中做)

目录包含这样的文件,例如:

mysql-2016-01-24/     *<--  dirname*
    adsoglasi-2016-01-24-05.35.gz
    adsoglasi-2016-01-24-09.35.gz
    adsoglasi-2016-01-24-13.35.gz
    adsoglasi-2016-01-24-17.35.gz
    adsoglasi-2016-01-24-21.35.gz
    ehoplit-2016-01-24-05.35.gz
    ehoplit-2016-01-24-09.35.gz
    ehoplit-2016-01-24-13.35.gz
    ehoplit-2016-01-24-17.35.gz
    ehoplit-2016-01-24-21.35.gz
    posavje-2016-01-24-05.35.gz
    posavje-2016-01-24-09.35.gz
    posavje-2016-01-24-13.35.gz
    posavje-2016-01-24-17.35.gz
    posavje-2016-01-24-21.35.gz
    export-mysql-baze-2016-01-24-05.35.log
    export-mysql-baze-2016-01-24-09.35.log
    export-mysql-baze-2016-01-24-13.35.log
    export-mysql-baze-2016-01-24-17.35.log
    export-mysql-baze-2016-01-24-21.35.log
    flora-2016-01-24-05.35.gz
    flora-2016-01-24-09.35.gz
    flora-2016-01-24-13.35.gz
    flora-2016-01-24-17.35.gz
    flora-2016-01-24-21.35.gz
    karcher-2016-01-24-05.35.gz
    karcher-2016-01-24-09.35.gz
    karcher-2016-01-24-13.35.gz
    karcher-2016-01-24-17.35.gz
    karcher-2016-01-24-21.35.gz
    knjigarna-2016-01-24-05.35.gz
    knjigarna-2016-01-24-09.35.gz
    knjigarna-2016-01-24-13.35.gz
    knjigarna-2016-01-24-17.35.gz
    knjigarna-2016-01-24-21.35.gz
    mysql-2016-01-24-05.35.gz
    mysql-2016-01-24-09.35.gz
    mysql-2016-01-24-13.35.gz
    mysql-2016-01-24-17.35.gz
    mysql-2016-01-24-21.35.gz
    mysqlshow_grants-2016-01-24-05.36.49.gz
    mysqlshow_grants-2016-01-24-09.36.50.gz
    mysqlshow_grants-2016-01-24-13.36.48.gz
    mysqlshow_grants-2016-01-24-17.36.48.gz
    mysqlshow_grants-2016-01-24-21.36.49.gz
    pohistvo-2016-01-24-05.35.gz
    pohistvo-2016-01-24-09.35.gz
    pohistvo-2016-01-24-13.35.gz
    pohistvo-2016-01-24-17.35.gz
    pohistvo-2016-01-24-21.35.gz
    akord-2016-01-24-05.36.gz
    akord-2016-01-24-09.36.gz
    akord-2016-01-24-13.36.gz
    akord-2016-01-24-17.36.gz
    akord-2016-01-24-21.36.gz
    ekomprof-2016-01-24-05.36.gz
    ekomprof-2016-01-24-09.36.gz
    ekomprof-2016-01-24-13.36.gz
    ekomprof-2016-01-24-17.36.gz
    ekomprof-2016-01-24-21.36.gz
    gume-2016-01-24-05.36.gz
    gume-2016-01-24-09.36.gz
    gume-2016-01-24-13.36.gz
    gume-2016-01-24-17.36.gz
    gume-2016-01-24-21.36.gz
    orchestra_test-2016-01-24-05.36.gz
    orchestra_test-2016-01-24-09.36.gz
    orchestra_test-2016-01-24-13.36.gz
    orchestra_test-2016-01-24-17.36.gz
    orchestra_test-2016-01-24-21.36.gz

这是每天在单独的目录中完成的

mysql-2015-11-16/
mysql-2015-11-19/

-- || --

mysql-2016-01-18/
mysql-2016-01-19/
mysql-2016-01-20/
mysql-2016-01-21/
mysql-2016-01-22/
mysql-2016-01-23/
mysql-2016-01-24/
...

我正在寻找的目录将只保留最新的日期和时间文件名,并且每个“重复”的类似文件都会被删除(它们会弄乱空间),

我希望得到的输出:

mysql-2015-11-16/
                adsoglasi-2016-01-16-21.35.gz
                ehoplit-2016-01-16-21.35.gz
                posavje-2016-01-16-21.35.gz
                export-mysql-baze-2016-01-16-21.35.log
                flora-2016-01-16-21.35.gz
                karcher-2016-01-16-21.35.gz
                knjigarna-2016-01-16-21.35.gz
                mysql-2016-01-16-21.35.gz
                mysqlshow_grants-2016-01-16-21.36.49.gz
                pohistvo-2016-01-16-21.35.gz
                akord-2016-01-16-21.36.gz
                ekomprof-2016-01-16-21.36.gz
                gume-2016-01-16-21.36.gz
                orchestra_test-2016-01-16-21.36.gz
-- || --
mysql-2015-11-19/
                ....filenames with date ...2015-11-19... 
-- || --
mysql-2016-01-24/
                adsoglasi-2016-01-24-21.35.gz
                ehoplit-2016-01-24-21.35.gz
                posavje-2016-01-24-21.35.gz
                export-mysql-baze-2016-01-24-21.35.log
                flora-2016-01-24-21.35.gz
                karcher-2016-01-24-21.35.gz
                knjigarna-2016-01-24-21.35.gz
                mysql-2016-01-24-21.35.gz
                mysqlshow_grants-2016-01-24-21.36.49.gz
                pohistvo-2016-01-24-21.35.gz
                akord-2016-01-24-21.36.gz
                ekomprof-2016-01-24-21.36.gz
                gume-2016-01-24-21.36.gz
                orchestra_test-2016-01-24-21.36.gz

...现在这不是一个更好的列表:-)

但由于我在使用 fdupes 或类似工具之类的“工具”方面没有取得任何成功,因此我正在寻求专业人士的帮助。

TY, 最好的问候。

【问题讨论】:

  • 为什么会有多个export-mysql-baze? “只有最新的”规则在这里不适用吗?
  • @Benjamin W. :......应该,我正在手动编辑(删除)这些行。列表已更正。

标签: linux bash duplicates filenames


【解决方案1】:

幸运的是,这些日期戳采用 ISO 表示法,带有年-月-日,因此简单地按 ascii 排序,也是按日期排序的。这使得这些事情变得容易。仅依靠“ls”排序以正确的顺序获取文件,然后我们可以读取,比较日期之前的部分,如果前一个具有相同的基础部分,那么我们可以删除前一个。

假设确实这些文件夹中的所有文件都具有该模式(特别是如果基本名称部分中不存在“破折号-年-破折号”模式 - 如果不确定,您必须使正则表达式更长确保仅匹配日期+序列+扩展名)。首先让我们看看会删除什么,在这样一个文件夹中执行:

ls | perl -nle '($b)=m{^(.*?)-2\d\d\d-.*}; print $fn if $fn && $b eq $p_b; $p_b=$b; $fn=$_;'

要真正删除这些文件,只需将“print”替换为“unlink”语句:

ls | perl -nle '($b)=m{^(.*?)-2\d\d\d-.*}; unlink $fn if $fn && $b eq $p_b; $p_b=$b; $fn=$_;'

要对所有这些文件夹执行此操作,请 cd 进入包含所有 mysql-YYYY-MM-DD 文件夹的父文件夹:

for d in mysql*; do (cd $d;
    ls | perl -nle '($b)=m{^(.*?)-2\d\d\d-.*}; unlink $fn if $fn && $b eq $p_b; $p_b=$b; $fn=$_;'
); done

-- 编辑--

显然你有别名“ls”到“ls -l”。完全避免“ls”:

find . -maxdepth 1 -type f -print0 | sort | perl -0x00 -ne '($b)=m{^(.*?)-2\d\d\d-.*}; unlink $fn if $fn && $b eq $p_b; $p_b=$b; $fn=$_;'

但是,如果您甚至不确定作为输入提供的所有文件都不是预期的格式,那么也许您应该更具体地确定要处理的文件以及要排除的文件。现在该模式假定文件名中必须存在模式“-2\d\d\d-”(破折号,数字 2,后跟 3 个数字,后跟破折号),并且该部分开始日期戳。

例如匹配格式为“-YYYY-MM-DD-”的完整日期(包括后面的破折号),并尽可能位于名称的末尾;

find . -maxdepth 1 -type f -print0 | sort | 
perl -0x00 -ne '($b)=m{^(.*)-2\d\d\d-\d\d-\d\d-.*}; unlink $fn if $fn && $b eq $p_b; $p_b=$b; $fn=$_;'

该日期之前的任何内容都被视为比较的基准;该日期和之后的内容被认为是“模糊”部分,仅用于排序。

【讨论】:

  • 你不想或不需要ls。 shell 会将任何通配符按字母顺序展开。另见mywiki.wooledge.org/ParsingLs
  • @tripleee : 使用 "find": find ./ -type f -printf "%f\n" |排序 | perl -nle '($b) ... 当我得到一些输出时,它看起来很有希望。
【解决方案2】:

@PBI:

不幸的是,这个

ls | perl -nle '($b)=m{^(.*?)-2\d\d\d-.*}; print $fn if $fn && $b eq $p_b; $p_b=$b; $fn=$_;' 

不会产生任何想要的输出(这是实际输出):

total 569356
drwxr-xr-x  2 root   root      4096 Jan 17 21:36 ./

“ls”输出:

--  || --
-rw-r--r--  1 root   root  22247827 Jan 17 05:35 akord-2016-01-17-05.35.gz
-rw-r--r--  1 root   root  22266602 Jan 17 09:35 akord-2016-01-17-09.35.gz
-rw-r--r--  1 root   root  22287951 Jan 17 13:35 akord-2016-01-17-13.35.gz
-rw-r--r--  1 root   root  22248103 Jan 17 17:35 akord-2016-01-17-17.35.gz
--  || --

在行首打印文件大小和所有者,这使 Perl 无法对文件名进行排序。

但是……“查找”命令可以很好地打印出预期的结果:

find ./ -type f -printf "%f\n" | sort | perl -nle '($b)=m{^(.*?)-2\d\d\d-.*}; print $fn if $fn && $b eq $p_b; $p_b=$b; $fn=$_;'

.

adsoglasi-2015-12-17-05.35.gz
adsoglasi-2015-12-17-09.35.gz
adsoglasi-2015-12-17-13.35.gz
adsoglasi-2015-12-17-17.35.gz

它应该打印的究竟是什么,而不是“源”列表:

adsoglasi-2015-12-17-05.35.gz
adsoglasi-2015-12-17-09.35.gz
adsoglasi-2015-12-17-13.35.gz
adsoglasi-2015-12-17-17.35.gz
adsoglasi-2015-12-17-21.35.gz

现在最后一个文件被省略了(yaaay :-),因此它产生了要删除的文件列表!很不错!

重要提示!

没有“sort”的“find ...”也不会输出任何有用的东西,除了一个保留在Perl“缓冲区”中的文件名(据我所知)

【讨论】:

  • 您已经将“ls”别名为“ls -l”。为避免使用别名,请执行“\ls”
  • 确实,"\ls" 完成了这项工作(顺便说一句,谁不给 "ls" 起别名 :-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-06-10
  • 1970-01-01
  • 2019-12-08
  • 2015-10-14
  • 2011-01-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多