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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/520437/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 20:40:08  来源:igfitidea点击:

Bash/DOS/PowerShell script to list most recent versions of files?

bashpowershellshelldos

提问by ilitirit

We have a list of (let's say 50) reports that get dumped into various folders depending on certain conditions. All the reports have standard names eg. D099C.LIS, D18A0.LIS etc.

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

Sometimes a report can exist in up to 5 different locations, and I need to generate a list of all the locations of the most recent version of each report.

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

I can do it easily using code, or redirecting "dir" or "ls" output into a text file and then manipulating it in Excel, but I'd prefer a simpler (hopefully a one-liner) solution either using DOS, bash, or PowerShell.

我可以使用代码轻松完成,或者将“dir”或“ls”输出重定向到文本文件中,然后在 Excel 中对其进行操作,但我更喜欢使用 DOS、bash、或 PowerShell。

The best I've come up with so far in PowerShell (I've done something similar using bash) is:

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

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

That will recursively list all files with *.lis extension, then sort it by name (asc) and date (desc), and then display the directory, name, and date.

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

This gives this sort of output:

这给出了这种输出:

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

What I obviously need to do now is remove the files that aren't the most recent versions, so that the output looks like this (not too worried about formatting yet):

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

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

Anyone have any ideas?

谁有想法?

[edit] Some good ideas and answers to this question. Unfortunately I can't mark all as accepted, but EBGreen's (edited) answer worked without modification. I'll add working solutions here as I verify them.

[编辑] 这个问题的一些好主意和答案。不幸的是,我无法将所有内容都标记为已接受,但 EBGreen(已编辑)的答案无需修改即可工作。当我验证它们时,我将在此处添加工作解决方案。

bash:

重击:

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

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

回答by EBGreen

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

回答by ilitirit

Another alternative in PowerShell, more "script" like:

PowerShell 中的另一种选择,更多的“脚本”,如:

ls -r . *.lis | sort LastWriteTime | %{$f=@{}} {$f[$_.Name]=$_} {$f.Values} | ft Directory,Name,LastWriteTime
  1. get the files recursively
  2. sort them ascending by last write time
  3. initialize a hashmap (associative array)
  4. for each file assign it using the name as key - later entries will overwrite previous ones
  5. get the Values of the hashmap (excluding keys)
  6. format as a table
  1. 递归获取文件
  2. 按上次写入时间对它们进行升序排序
  3. 初始化一个 hashmap(关联数组)
  4. 对于每个文件,使用名称作为键分配它 - 以后的条目将覆盖以前的条目
  5. 获取哈希图的值(不包括键)
  6. 格式为表格

Note, the FileInfo objects are retained throughout the pipeline. You can still access any property/method of the objects or format them any way you like.

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

回答by Nick Fortescue

In bash you could pipe your answers through uniq. I'm not sure of the exact structure for the results of your bash 1-liner but the right arguments to -w N and -s N ought to do it.

在 bash 中,您可以通过uniq传递您的答案。我不确定 bash 1-liner 结果的确切结构,但 -w N 和 -s N 的正确参数应该这样做。

回答by amit

The problem seems to be finding unique based on particular field. awk can be used to solve this problem. Saw this blog entrywhich has one approach. For eg, in bash one could do:

问题似乎是根据特定领域找到独特的。awk 可以用来解决这个问题。看到这个博客条目,它有一种方法。例如,在 bash 中可以这样做:

find . -name "*.lis" -print | xargs ls -tr | awk -F/ '!x[$NF]++'

找 。-name "*.lis" -print | xargs ls -tr | awk -F/ '!x[$NF]++'

回答by amit

Powershell:

电源外壳:

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

Explanation:

解释:

  1. get the files recursively
  2. sort the files descending by LastWriteTime
  3. sort the files by Name, selecting unique files (only the first).
  4. format the resulting FileInfo objects in a table with Directory, Name and Time
  1. 递归获取文件
  2. 按 LastWriteTime 降序对文件进行排序
  3. 按名称对文件进行排序,选择唯一的文件(仅第一个)。
  4. 使用目录、名称和时间在表中格式化生成的 FileInfo 对象

Alternative which does not rely on sortbeing stable:

不依赖排序稳定的替代方案:

ls -r . *.lis | sort -desc LastWriteTime | group Name | %{$_.Group[0]} | ft Directory,Name,LastWriteTime
  1. get the files recursively
  2. sort the files descending by LastWriteTime
  3. group the files by name
  4. for each group select the first (index zero) item of the group
  5. format the resulting FileInfo objects in a table with Directory, Name and Time
  1. 递归获取文件
  2. 按 LastWriteTime 降序对文件进行排序
  3. 按名称对文件进行分组
  4. 对于每个组,选择该组的第一个(索引为零)项目
  5. 使用目录、名称和时间在表中格式化生成的 FileInfo 对象

回答by Fregus

ls -ARFlrt | awk '{print $6,$7,$8}'|grep 2010|sort -n

ls -ARFlrt | awk '{print $6,$7,$8}'|grep 2010|sort -n

Was looking for similar. The above has helped me get listing I was after in bash. The grep is optional (of course). \thanks

正在寻找类似的。以上帮助我获得了我在 bash 中所追求的列表。grep 是可选的(当然)。\谢谢

回答by AndyB

Can you use perl? Something like:

你会用perl吗?就像是:

your command| perl 'while (<STDIN>) { ($dir,$name,$date) = split; $hash{$name} = ($dir,$date);} foreach (keys %hash) { print "$hash{$}[0] $$hash{$_}[1]\n"; }'

你的命令| perl 'while (<STDIN>) { ($dir,$name,$date) = split; $hash{$name} = ($dir,$date);} foreach (keys %hash) { print "$hash{$ }[0] $$hash{$_}[1]\n"; }'

This could be wrong in the details (it's been too long since I used perl in anger) but the basic idea being to keep a hash of results keyed on filename and always overwriting the previous entry when encountering a new entry. That way, as long as the order of lines coming in is right, you'll only get the most recently touched files coming out.

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

回答by Shay Levy

$f = ls -r -fi *.lis | sort name,lastWriteTime -desc

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

# remove -whatIf 删除文件

$f[1..$f.length] | Remove-Item -whatIf

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