排序find -exec ls的输出


14

是否可以find … -exec ls -ls ;按文件名按字母顺序对输出进行排序?

这是我的cron命令:

find /home/setefgge/public_html -type f -ctime -1 -exec ls -ls {} \;

这个命令在大多数情况下都可以。但是结果没有按照任何有意义的顺序排序。如果将它们按文件名字段进行排序将非常有帮助。


1
使用zsh?ls -ls **/*(.)
凯文(Kevin)

Answers:


14

我假设您的文件名不包含换行符。

find /home/setefgge/public_html -type f -ctime -1 -exec ls -nls {} + | sort -k 10

使用+而不是;终止-exec操作,可以通过批量调用来加快操作速度ls。您可以通过sort命令对管道进行排序。告诉它从第10个字段开始排序(前9个是元数据:阻止,权限,链接计数,用户,组,大小和3个日期/时间字段)。该选项-n告知ls用户和组使用数字值,从而避免了用户名或组名包含空格的风险。

另外,使用zsh,您可以通过使用glob限定符收集和排序文件并在命令行太长的情况下zargs运行ls多次来不假思索地使用任何名称。您确实需要GNU ls(特别是它的-f选项)来避免进行重新排序ls(另一种方法是ls使用zsh 进行仿真zstat)。

autoload -U zargs
zargs -- /home/setefgge/public_html/**/*(.c-2) -- ls -lnsf

非常感谢!使用您发送的第一个命令进行排序。如果使用较短的路径,数字是否仍为10?例如,如果我从/ home / setefgge而不是public_html运行相同的命令?
MaJ 2014年

@MaJ 10是已跳过字段的数量,与文件名的大小无关。
吉尔(Gilles)'所以

谢谢。感谢您的帮助,也感谢其他人提供的帮助。我认为这个问题已经解决。我的cron命令现在正在对文件进行排序。这是我第一次向Stackexchange提交问题。我没有看到“已解决”选项。如果您知道如何解决此问题,请继续进行。谢谢!
MaJ 2014年

@MaJ我们将问题标记为已解决的最接近的事情是将答案之一标记为已接受。请求者只有您才能这样做。为此,请单击对您最有帮助的答案旁边的复选标记。如果您接受答案,您将再获得2个声誉点,之后您就可以上传帖子;您可以对发现有帮助的所有帖子进行投票。有关更多信息,请参见游览页面帮助页面,了解有人回答您的问题时如何处理
吉尔(Gilles)“所以,别再邪恶了”

1

为什么不通过管道对find的结果进行排序,然后对每行执行ls呢?

find . -type f -ctime -1 | sort | while IFS= read -r filename; do ls -ls "$filename"; done

1

POSIX关于ls -long清单中的日期有这样的说法:

<date and time>字段应包含文件上次修改的适当日期和时间戳。在POSIX语言环境中,该字段应等于以下日期命令的输出:

date "+%b %e %H:%M"

...如果文件在最近六个月内已被修改,或者:

date "+%b %e %Y"

考虑到这一点,并确保如果文件名中包含任何换行符,也可以使用POSIX指定的ls -q选项正确地换行,则为ls结果准备一个正则表达式相对简单,而一点也不find做:

d=$(date "+%b %e") y=$(date --date=yesterday "+%b %e")
echo "$d" "$y"

###OUTPUT###
Jul  5 Jul  4

grep为此,您将仅返回包含表示今天或昨天日期的字符串的行。以下命令对此有所补充:

ls -alRcq | sed "1H;/^-/!{/./d;N;h};/$d\|$y/!d;x;/\n/p;g"

ls 选项包括:

  1. -a 返回目录中的所有文件-包括以。开头的文件 .dot
  2. -l 长时间列出
  3. -R 递归列出所有子目录
  4. -c 显示修改时间而不是访问时间
  5. -q返回Shell Glob,?而不是\t文件名中的不可打印或Ab字符

这些结果将通过仅匹配的|pipe文件传递sed

  1. 路径名前面的空白行和下面的行
  2. - (也就是-不d用于目录)开头的行也包含您的date
  3. 但是,它不会打印路径名行,除非它们所命名的目录实际上包含您要过滤的文件。

输出看起来像这样:

ls -alRcq --color=always | 
sed "1H;/^-/!{/./d;N;h};/$d\|$y/!d;x;/\n/p;g"

###OUTPUT###
.:
-rw------- 1 mikeserv mikeserv   2086 Jul  4 10:52 .bash_history
-rw------- 1 mikeserv mikeserv   2657 Jul  4 15:20 .lesshst
-rw-r--r-- 1 mikeserv mikeserv    681 Jul  5 05:18 .zdirs
-rw------- 1 mikeserv mikeserv 750583 Jul  5 08:28 .zsh_history
-rw-r--r-- 1 mikeserv mikeserv    166 Jul  4 23:02 Terminology.log
-rw-r--r-- 1 mikeserv mikeserv 433568 Jul  4 13:34 shot-2014-06-22_17-10-16.jpg
-rw-r--r-- 1 mikeserv mikeserv 445192 Jul  4 13:34 shot-2014-06-22_17-11-06.jpg

./.cache/efreet:
-rw------- 1 mikeserv mikeserv  37325 Jul  4 22:51 desktop_localhost_C.eet
-rw------- 1 mikeserv mikeserv  37325 Jul  4 23:30 desktop_localhost_en_US.eet
-rw------- 1 mikeserv mikeserv  24090 Jul  4 22:51 desktop_util_localhost_C.eet
-rw------- 1 mikeserv mikeserv  24090 Jul  4 23:30 desktop_util_localhost_en_US.eet
-rw------- 1 mikeserv mikeserv  16037 Jul  4 23:30 icon_themes_localhost.eet
-rw------- 1 mikeserv mikeserv   3117 Jul  4 23:30 icons___efreet_fallback_localhost.eet
-rw------- 1 mikeserv mikeserv 768039 Jul  4 23:30 icons_gnome_localhost.eet
-rw------- 1 mikeserv mikeserv  18589 Jul  4 23:30 icons_hicolor_localhost.eet

./.config:
-rw-r--r-- 1 mikeserv mikeserv   30 Jul  4 19:10 pavucontrol.ini

./.config/chrome:
-rw-r--r-- 1 mikeserv mikeserv 94332179 Jul  4 13:36 conf.tar.lz4.bak

是的,它甚至可以与LS_COLORS- 一起使用,这cron当然不是您的优先事项,但是,嘿,您的选择是开放的。

无论如何,与其他可能的解决方案相比,这提供了一些明显的优势。

  1. 首先,find+ ls涉及多个调用-这仅涉及单个ls进程,这就是为什么它能够可靠地对所有内容进行排序的原因-默认情况下会这样做-因此sort也被辅助。

  2. 任何解决方案,涉及findsortls被几乎做所有的工作两次。lsfind会解析每个路径名和stat每个文件。lssort会将所有结果排序。最好只使用single ls

  3. 然后当然有这个答案的datesed部分。需要注意的重要一点是,您要做的很辛苦,首先要获取正则表达式-只能获取一次-然后再修剪一个结果列表,而不是说获取结果,获取结果,对结果进行排序和对结果进行排序。

  4. 这不会破坏包含换行符的文件名,就像其他解决方案一样。该解决方案确实有其自身的警告-我将在下面进行解释-但它们是微小且易于处理的。我认为,这是这里最可靠的解决方案。

在两种情况下,上述命令可能会导致您遇到问题。第一个涉及?文件名中的glob-尽管它已经比这里提供的任何其他解决方案都更可靠,并且您单独遇到a的可能性?很小,但有可能解决这些glob可以匹配多个文件名。请参阅以获取有关此主题的更多信息。

另一种可能性是误报-例如,如果您的文件名实际上与date我们要搜索的字符串匹配,grep但实际上在那一天的任何时候都没有修改。我没有指望这是一个问题,但是,如果有的话,请问一下,我也许可以帮助您使正则表达式更加具体,以解决此问题。


0

您实际上可以结合使用find,xargs和ls。

这是一个示例命令: find . -type f -print0 | xargs -0 ls -lt

  • find 将递归查找当前目录下的所有文件。
  • xargs将ls在一次调用中将此文件列表传递给命令(提供的find返回少于ARG_MAX文件)。
  • ls -lt 将按时间对这些文件进行排序并格式化输出

为了检索您的系统,ARG_MAX您可以输入:

$ getconf ARG_MAX
> 2621440

-1
ls -l $(find /home/setefgge/public_html -type f -ctime -1 | sort)

1
ls自己进行排序,因此find通过管道传递通过的输出sort是无用的。此外,您的命令会破坏包含空格的文件名(其中包括空格),并且如果文件名过多,则该命令将失败。
吉尔(Gilles)'所以
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.