我有一个程序,它在一个命令行中接受一些文件作为参数。我想用以相反时间顺序列出的目录中的所有文件来调用它。
例如:
我在目录中有以下按逆时间顺序排列的文件
$ 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) — 默认为.
— 使用具有两个的通配符/全局扩展“全局限定符”在后面的括号中:
.
-- 必须是常规文件(不是目录或符号链接等)om
--o
按修改时间对结果列表进行 rder(排序),最新的排在前面
正是这个om
glob 限定符完成了这里的所有实际工作。
这是一些示例运行;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 下的第一个文件名中有一个换行符,用tree
with表示\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:])