对 find -exec ls 的输出进行排序

对 find -exec ls 的输出进行排序

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

这是我的 cron 命令:

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

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

答案1

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

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

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

或者,使用 zsh,您可以通过使用来摆脱对任何名称的假设全局限定符收集和排序文件zargsls如果命令行太长,则运行多次。您确实需要 GNU ls(特别是它的-f选项)来避免重新排序ls(另一种方法是ls使用 zsh进行模拟zstat)。

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

答案2

为什么不通过排序传递 find 的结果,然后对每一行执行 ls ?

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

答案3

POSIX 对于 ong 列表中的日期有这样的说法ls -l

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

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

...如果文件在过去六个月内被修改,或者:

date "+%b %e %Y"

考虑到这一点,并确保如果文件名中有任何换行符,它们也会使用 POSIX 指定的选项正确匹配,那么为结果ls -q准备正则表达式相对容易,根本不需要:lsfind

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返回目录中的所有文件 - 包括以 a 开头的文件.dot
  2. -l长列表
  3. -R递归列出所有子目录
  4. -c显示修改时间而不是访问时间
  5. -q返回 shell glob ,而不是文件名中的?不可打印字符或ab 字符\t

这些结果将传递到仅匹配的|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. 任何涉及findandsort的解决方案ls都在做全部工作的两次。ls并将find解析每个路径名和stat每个文件。ls并且sort都会对所有结果进行排序。最好只使用单个ls.

  3. 当然还有这个答案的date和部分。sed需要注意的重要一点是,您完成了最困难的部分并首先获取正则表达式 - 并且仅一次 - 然后您只修剪单个结果列表,而不是说,获取结果,获取结果,对结果进行排序和对结果进行排序。

  4. 这不会像其他解决方案那样破坏包含换行符的文件名。这个解决方案确实有其自身的警告 - 我接下来会解释 - 但它们很微小且易于处理。在我看来,这是最强大的解决方案。

在两种情况下,上述命令可能会给您带来问题。第一个涉及?文件名中的 glob - 虽然它已经是比此处提供的任何其他解决方案更强大的解决方案,并且您遇到 a 的可能性?本身足够小,但有可能解决这些 glob可以匹配多个文件名。请参见有关此主题的更多信息。

另一种可能性涉及误报 - 例如,如果您有一个文件名实际上date与我们正在搜索的字符串匹配grep,但实际上在任何一天都没有修改过。我不认为这是一个问题,但是,如果是这样,请询问一下,我可能可以帮助您使正则表达式更具体,以便处理这个问题。

答案4

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

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

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

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

$ getconf ARG_MAX
> 2621440

相关内容