我需要在 shell 脚本中加载具有相同文件名的多个文件,但在每个文件名前面附加的是 YYMMDDPERSONNEL 示例:231102PERSONNEL 和 230103PERSONNEL 同一目录中还有许多其他文件,因此文件名在排序中很重要。我需要对要加载的文件从最旧到最新进行排序。
目前我所拥有的只是设计用于一次处理一个文件。
答案1
这是一个简单的任务,有管道。
find . -maxdepth 1 -type f -name '*PERSONNEL.gz' -print | \
sed -e 's%^./%%' | \
sort | \
xargs -r /bin/echo
阅读man
页面。
这是一个快速概述:
find
打印文件名列表STDOUT
sed
使它看起来更好(更改./231102PERSONNEL.gz
为231102PERSONNEL.gz
)sort
对列表进行排序。xargs
放置尽可能多的文件(请xargs --show-limits </dev/null
参阅你的限制)并对列表的其余部分重复“命令”/bin/echo
是一个占位符。
答案2
默认情况下,Shell 全局按词汇顺序展开,并且您的情况下的词汇顺序与时间顺序 (顺序的)文件的顺序,只要它们都来自同一世纪(例如,从 1900 年到 1999 年,忽略 20世纪实际上是从 1901 年到 2000 年)。
和zsh
:
set -o extendedglob
for f ( [0-9](#c6)PERSONNEL.sql.gz(N) ) gunzip < $f | your-sql-loader
(或者,[0-9](#c6)PERSONNEL.sql.gz(NOn)
如果您需要O
按 ame 顺序排列文件n
,则按照您最初的要求相反(大写o
))。
假设your-sql-loader
可以从标准输入获取输入。如果需要将其作为文件名参数传递:
for f ( [0-9](#c6)PERSONNEL.sql.gz(N) ) your-sql-loader <(gunzip < $f)
或者,如果该文件名参数必须是常规文件:
for f ( [0-9](#c6)PERSONNEL.sql.gz(N) ) your-sql-loader =(gunzip < $f)
您很可能能够做到:
gunzip -dc -- [0-9](#c6)PERSONNEL.sql.gz | your-sql-loader
也就是说,将所有反向排序的文件的所有未压缩内容串联起来your-sql-loader
。
更一般地说,很少需要在磁盘上存储文件的未压缩版本。最好即时解压缩它并同时将其提供给使用它的任何应用程序。
如果消费者应用程序不按顺序读取数据(如果这意味着是的话,那么这里会令人惊讶,那么您只需要在磁盘上解压缩它(就像=(...)
上面的方法完成的那样,在临时文件中获取输出)) gunzip
SQL)。
如果您确实必须使用 (t)csh 正如标签所暗示的那样,这在本世纪将是非常令人惊讶的,假设文件名不包含换行符的等效内容将是:
gunzip -dc -- "`ls -rd -- [0-9][0-9][01][0-9][0-3][0-9]PERSONNEL.sql.gz`" | your-sql-loader
其中ls -r
按名称对文件进行反向排序;其"`...`"
输出被检索并分成非空行成分。
由于csh
没有 zsh[0-9](#c6)
或 ksh的等效项{6}([0123456789])
来匹配 6 位数字,因此我们专门匹配每个数字,并借此机会更严格地匹配月份和日期数字。
oe[code]
如果您有上个世纪的文件,则可以使用 the或o+function
glob 限定符在 zsh 中定义自定义排序顺序。
[0-9](#c6)PERSONNEL.sql.gz(Noe['REPLY[1,0]=$(( 19 + ($REPLY[1,2] < 70) )'])
也就是说,指示 zsh 根据我们在其前面添加 20 或 19 的文件名对 glob 进行排序,具体取决于前 2 位数字是否构成大于或小于 70 的数字(您需要调整基于您的实际数据集的截止年份;此处选择 1970 年,因为这是 Unix 纪元时间的开始)。