![按日期文件名的顺序从文件中提取行数](https://linux22.com/image/1155807/%E6%8C%89%E6%97%A5%E6%9C%9F%E6%96%87%E4%BB%B6%E5%90%8D%E7%9A%84%E9%A1%BA%E5%BA%8F%E4%BB%8E%E6%96%87%E4%BB%B6%E4%B8%AD%E6%8F%90%E5%8F%96%E8%A1%8C%E6%95%B0.png)
我有一个文件夹,其中包含 csv 文件的文件名是日期,即:January-01-2018.csv
,,January-02-2018.csv
...,April-30-2018.csv
。
最好使用 Bash,我想从每个 csv 文件中提取行数,但按日期顺序进行。即,我希望提取行数,然后January-01-2018.csv
...January-02-2018.csv
然后April-30-2018.csv
等等。
目前,我所拥有的只有:
for filename in $(ls *.csv); do cat $filename | wc -l >> by_day.dat; done
但这确实不是按照“日期升序”顺序处理我的操作。
关于如何实现这一点,有什么建议吗?我想使用 bash 来做到这一点。
答案1
您可以通过组合一些常用工具来实现此目的:
find
列出所有 .csv 文件(无序)并为每个文件执行一条命令basename
.csv
从路径中提取不带扩展名的文件名date
解释文件名中的日期规范并将其转换为易于排序的数字,例如自 1970 年以来的秒数。echo
为每个文件在一行中打印计算出的数字和实际文件路径sort
根据转换后的日期数字对文件路径进行排序cut
从组合列表中再次仅提取文件路径xargs cat
通过将所有文件名按顺序传递给命令来构造一个命令cat
以将它们连接起来。
如果我们要处理的所有文件都位于名为的文件夹中,则完整的行如下所示datecsv
:
$ find datecsv/ -name '*.csv' -exec bash -c 'echo "$(date -d "$(basename -s.csv "{}")" +%s) {}"' \; | sort -n | cut -d' ' -f2- | xargs cat
2018,1,1,aaa
2018,1,1,bbb
2018,1,2,ccc
2018,1,2,ddd
2018,4,30,eee
2018,4,30,fff
产生上述输出的示例文件如下:
$ cat datecsv/April-30-2018.csv
2018,4,30,eee
2018,4,30,fff
$ cat datecsv/January-01-2018.csv
2018,1,1,aaa
2018,1,1,bbb
$ cat datecsv/January-02-2018.csv
2018,1,2,ccc
2018,1,2,ddd
由于您只想要每个文件的行号,因此命令如下:
$ find datecsv/ -name '*.csv' -exec bash -c 'echo "$(date -d "$(basename -s.csv "{}")" +%s) {}"' \; | sort -n | cut -d' ' -f2- | xargs -n1 wc -l
2 datecsv/January-01-2018.csv
2 datecsv/January-02-2018.csv
2 datecsv/April-30-2018.csv
唯一的变化是最后一部分,我们使用xargs -n1 wc -l
而不是xargs cat
上面的。
一些说明:上述方法依赖于文件名是date
可以解析的格式。您提供的示例名称就是这种情况,但如果格式发生变化,它可能会中断。它还要求文件名以小写字母结尾.csv
。不确定文件名中的某些特殊字符是否会破坏某些内容(空格应该是安全的,换行符肯定会破坏它)。