如何通过命令按相反时间顺序列出文件并将它们作为参数传递给另一个命令?

如何通过命令按相反时间顺序列出文件并将它们作为参数传递给另一个命令?

我有一个程序,它在一个命令行中接受一些文件作为参数。我想用以相反时间顺序列出的目录中的所有文件来调用它。

例如:

我在目录中有以下按逆时间顺序排列的文件

$ ls -tr
 Introduction.pdf  'Object-Oriented Data Model.pdf' 

我可以直接运行我的程序,

myprogram Introduction.pdf  'Object-Oriented Data Model.pdf' 

但我想通过另一个命令来列出文件。由于一个文件名中存在空格,这将不起作用:

myprogram $(ls -tr)

我记得解析ls输出不是一个好的做法。我不确定是否find可以提供帮助。

那我能做什么呢?

谢谢。

答案1

如果您拥有最新版本的 GNU 实用程序,您可以让它们处理以 NULL 结尾的数据。这允许构建不受数据本身中的空格或换行符影响的管道。

我的测试工具是一个名为的快速脚本/tmp/args

#!/bin/bash
echo "This is args with $# value(s)"
for f in "$@"; do echo "> $f <"; done

您可以通过以下方式在命令行上为其提供一系列文件名,并按上次修改的文件时间排序:

find -type f -printf "%T@ %p\0" | sort -zn | sed -z 's/^[0-9.]* //' | xargs -0 /tmp/args

find命令在每个文件/路径名前面加上上次修改日期/时间的小数秒表示形式。这是按sort从最低(最旧)到最高(最新)的顺序处理的。去掉sed我们刚刚用来排序的前导数字,并将生成的文件名集传递给xargs.如果您希望省略文件名中的前导,请将 替换%p为。%P./

示例数据

# "c d" contains a space; "e f" contains a newline; "h" has leading whitespace
touch a 'e
f' g ' h ' 'c d' b

结果示例

This is args with 6 value(s)
> ./a <
> ./e
f <
> ./g <
> ./ h  <
> ./c d <
> ./b <

答案2

重击还不能轻松地按修改时间对文件进行排序,所以这是基于 zsh 的强制性答案。您不必切换到 zsh 作为登录 shell 即可使用其功能。

在这里,我设置了一个包装函数,它需要一个或两个参数;第一个参数是要执行的程序(例如myprogram);第二个可选参数是包含要传递给程序的文件的目录。如果不指定第二个参数,则默认为当前目录。

zeio() {
  # Zsh-based Execute with files In Order
  [ -d "${2:-.}" ] || return
  zsh -c "$1 \"${2:-.}\"/*(.om)"
}

当然,您可以随意命名。在对第二个参数(再次默认为当前目录)进行快速健全性检查后.,我们使用单个双引号字符串调用 zsh,其中包含程序和一些初始参数(参数#1)和目录(参数#1) 2) — 默认为.— 使用具有两个的通配符/全局扩展“全局限定符”在后面的括号中:

  1. .-- 必须是常规文件(不是目录或符号链接等)
  2. om--o按修改时间对结果列表进行 rder(排序),最新的排在前面

正是这个omglob 限定符完成了这里的所有实际工作。

这是一些示例运行;myprog是一个简单的 shell 脚本,用于演示它接收的参数,按顺序:

#!/bin/sh
for arg do
  printf 'Arg: ->%s<-\n' "$arg"
done

go.sh我保存该函数的文件。目录结构的其余部分是:

$ tree .
.
├── dir1
│   ├── 203142
│   ├── 203143
│   └── 203144
├── dir3
│   ├── first\012filename
│   ├── this is 3rd
│   └── this is second
├── dir two
│   ├── 203225
│   ├── 203226
│   └── 203227
├── go.sh
└── myprog

...我在每个子目录中按列出的顺序创建了三个文件集;我希望在执行该函数时以相同的顺序看到它们。 dir3 下的第一个文件名中有一个换行符,用treewith表示\012。结果是:

演示默认到当前目录的行为:

$ zeio ./myprog
Arg: ->./myprog<-
Arg: ->./go.sh<-

正常文件名演示

$ zeio ./myprog dir1
Arg: ->dir1/203142<-
Arg: ->dir1/203143<-
Arg: ->dir1/203144<-

目录中有一个空格

$ zeio ./myprog "dir two"
Arg: ->dir two/203225<-
Arg: ->dir two/203226<-
Arg: ->dir two/203227<-

文件名中有空格

$ zeio ./myprog dir3
Arg: ->dir3/first
filename<-
Arg: ->dir3/this is second<-
Arg: ->dir3/this is 3rd<-

答案3

(IFS=$'\n'; set -f; your_program $(ls -tr))

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

例子:

% touch 'a   b'
% touch 'c d'
% touch '*'
% (IFS=$'\n'; set -f; printf '%s\n' $(ls -tr))
e    f
a   b
c d
*

不支持$'...'字符串的标准 shell 的变体:

(IFS='
' ; set -f; your_program $(ls -tr))

简单的 python 包装器,即使文件名包含换行符也可以工作。用法即可this_wrapper your_program *

#! /usr/bin/python
import os
import sys

sys.argv[2:] = sorted(sys.argv[2:], key=os.path.getmtime)
os.execvp(sys.argv[1], sys.argv[1:])

相关内容