代码之家  ›  专栏  ›  技术社区  ›  ilitirit

Bash/DOS/PowerShell脚本列出最新版本的文件?

  •  5
  • ilitirit  · 技术社区  · 17 年前

    我们有一个(假设50个)报告的列表,这些报告根据特定条件被转储到不同的文件夹中。所有报告都有标准名称,例如D099C。LIS、D18A0.LIS等。

    有时,一份报告最多可以存在于5个不同的位置,我需要生成一份每个报告最新版本的所有位置的列表。

    我可以使用代码轻松完成,或者将“dir”或“ls”输出重定向到文本文件,然后在Excel中操作它,但我更喜欢使用DOS、bash或PowerShell的更简单(希望是单行)的解决方案。

    到目前为止,我在PowerShell中想出的最好的东西(我用bash做过类似的事情)是:

    ls -r -fi *.lis | sort @{expression={$_.Name}}, @{expression={$_.LastWriteTime};Descending=$true} | select Directory, Name, lastwritetime
    

    这将递归列出所有扩展名为*.lis的文件,然后按名称(asc)和日期(desc)排序,然后显示目录、名称和日期。

    这给出了这样的输出:

    C:\reports\LESE            D057A.LIS                  28/01/2009 09:00:43
    C:\reports\JCSW            D057A.LIS                  27/01/2009 10:50:21
    C:\reports\ALID            D075A.LIS                  04/02/2009 12:34:12
    C:\reports\JCSW            D075B.LIS                  05/02/2009 10:07:15
    C:\reports\ALID            D075B.LIS                  30/01/2009 09:14:57
    C:\reports\BMA3            D081A.LIS                  01/09/2008 14:51:36
    

    我现在显然需要做的是删除不是最新版本的文件,这样输出看起来就像这样(还不太担心格式):

    C:\reports\LESE            D057A.LIS                  28/01/2009 09:00:43
    C:\reports\JCSW            D075B.LIS                  05/02/2009 10:07:15
    C:\reports\BMA3            D081A.LIS                  01/09/2008 14:51:36
    

    有人有什么想法吗?

    [编辑] 这个问题的一些好主意和答案。不幸的是,我无法将所有内容标记为已接受,但EBGreen的(编辑过的)答案在没有修改的情况下仍然有效。在验证时,我将在此处添加工作解决方案。

    猛击:

     ls -lR --time-style=long-iso | awk 'BEGIN{OFS="\t"}{print $5,$6,$7,$8}' | grep ".LIS" | sort -k4 -k2r -k3r | uniq -f3
     ls -lR --time-style=long-iso | awk 'BEGIN{OFS="\t"}{print $5,$6,$7,$8}' | grep ".LIS" | sort -k4 -k2r -k3r | awk '!x[$4]++'
    

    PowerShell:

      ls -r -fi *.lis | sort @{expression={$_.Name}}, @{expression={$_.LastWriteTime};Descending=$true} | select Directory, Name, lastwritetime | Group-Object Name | %{$_.Group | Select -first 1}
      ls -r . *.lis | sort -desc LastWriteTime | group Name | %{$_.Group[0]} | ft Directory,Name,LastWriteTime
      ls -r -fi *.lis | sort @{expression={$_.Name}}, @{expression={$_.LastWriteTime};Descending=$true} | unique | ft Directory,Name,LastWriteTime
    
    8 回复  |  直到 17 年前
        1
  •  8
  •   EBGreen    17 年前
    ls -r -fi *.lis | sort @{expression={$_.Name}}, @{expression={$_.LastWriteTime};Descending=$true} | select Directory, Name, lastwritetime | Group-Object Name | %{$_.Group | Select -first 1}
    
        2
  •  2
  •   Nick Fortescue    17 年前

    在bash中,你可以通过管道传输你的答案 uniq 我不确定bash 1-liner结果的确切结构,但-w N和-s N的正确参数应该可以做到这一点。

        3
  •  2
  •   Uffe Uffe    17 年前

    PowerShell中的另一种选择,更像是“脚本”:

    ls -r . *.lis | sort LastWriteTime | %{$f=@{}} {$f[$_.Name]=$_} {$f.Values} | ft Directory,Name,LastWriteTime
    
    1. 递归获取文件
    2. 按上次写入时间升序排列
    3. 初始化哈希映射(关联数组)
    4. 对于每个文件,使用名称作为关键字进行分配-后面的条目将覆盖前面的条目
    5. 获取哈希映射的值(不包括键)
    6. 格式为表格

    注意,FileInfo对象在整个管道中都会保留。您仍然可以访问对象的任何属性/方法,或以任何您喜欢的方式对其进行格式化。

        4
  •  1
  •   amit    17 年前

    问题似乎在于根据特定领域找到独特之处。awk可以用来解决这个问题。看到这个了 blog entry 其具有一种方法。 例如,在bash中可以这样做:

    发现。-名称“*.lis”-打印|xargs ls-tr|awk-F/'!x[$NF]++'

        5
  •  1
  •   Uffe Uffe    17 年前

    动力壳:

    ls -r . *.lis | sort -desc LastWriteTime | sort -u Name | ft Directory,Name,LastWriteTime
    

    说明:

    1. 递归获取文件
    2. 按LastWriteTime降序排列文件
    3. 按名称对文件进行排序,选择唯一的文件(仅第一个)。
    4. 使用目录、名称和时间在表中格式化生成的FileInfo对象

    不依赖于 排序 稳定:

    ls -r . *.lis | sort -desc LastWriteTime | group Name | %{$_.Group[0]} | ft Directory,Name,LastWriteTime
    
    1. 递归获取文件
    2. 按LastWriteTime降序排列文件
    3. 按名称对文件进行分组
    4. 为每个组选择该组的第一个(索引零)项
    5. 使用目录、名称和时间在表中格式化生成的FileInfo对象
        6
  •  0
  •   AndyB    17 年前

    你能用perl吗?类似于:

    你的命令 |perl'while(<STDIN>){($dir,$name,$date)=拆分;$hash{$name}=($dir、$date);}foreach(键%hash){打印“$hash{$ }[0] $ $hash{$_}[1]\n“;}'

    这在细节上可能是错误的(我愤怒地使用perl已经太久了),但基本的想法是保持在文件名上键入结果的哈希值,并在遇到新条目时始终覆盖之前的条目。这样,只要行的顺序正确,您只会得到最近接触过的文件。

        7
  •  0
  •   Fregus    16 年前

    ls-ARFlrt|awk“{打印$6,$7,$8}”|grep 2010|排序-n

    我在寻找类似的东西。以上内容帮助我在bash中获得了想要的列表。 grep是可选的(当然)。 \谢谢

        8
  •  -1
  •   Shay Levy    17 年前

    $f=ls-r-fi*.lis|排序名称,lastWriteTime-desc

    #删除-whatIf删除文件

    $f[1..$f.length]|删除项目-whatIf

    推荐文章