【问题标题】:Bash shell script: recursively cat TXT files in foldersBash shell 脚本:递归地将文件夹中的 TXT 文件分类
【发布时间】:2019-01-09 20:58:39
【问题描述】:

我有一个结构如下的文件目录:

./DIR01/2019-01-01/Log.txt
./DIR01/2019-01-01/Log.txt.1
./DIR01/2019-01-02/Log.txt
./DIR01/2019-01-03/Log.txt
./DIR01/2019-01-03/Log.txt.1
...
./DIR02/2019-01-01/Log.txt
./DIR02/2019-01-01/Log.txt.1
...
./DIR03/2019-01-01/Log.txt

...等等。 每个DIRxx 目录都有许多按日期命名的子目录,它们本身有许多需要连接的日志文件。要连接的文本文件的数量各不相同,但理论上可能多达 5 个。我希望看到对日期目录中的每组文件执行以下命令(请注意,文件必须以相反的顺序连接):

cd ./DIR01/2019-01-01/
cat Log.txt.4 Log.txt.3 Log.txt.2 Log.txt.1 Log.txt > ../../Log.txt_2019-01-01_DIR01.txt

(我知道上面的命令会给出某些文件不存在的错误,但cat 无论如何都会做我需要的) 除了 cd 进入每个目录并运行上述 cat 命令之外,我如何将其编写到 Bash shell 脚本中?

【问题讨论】:

  • 使用find-exec
  • 您在这具体部分遇到了什么问题?它是否使用您的目录名称并将/s 转换为_s?它是否在目录上循环?如果您将问题范围缩小到足以确定您在确定如何执行时遇到困难的具体操作,我们可能在知识库中已有关于所有这些事情的问答条目。

标签: bash shell unix command-line


【解决方案1】:

如果您只想连接名称以Log.txt 开头的所有子目录中的所有文件,您可以执行以下操作:

for dir in DIR*/*; do 
    date=${dir##*/}; 
    dirname=${dir%%/*}; 
    cat $dir/Log.txt* > Log.txt_"${date}"_"${dirname}".txt; 
done

如果您需要以相反的数字顺序排列文件,从 5 到 1,然后是 Log.txt,您可以这样做:

for dir in DIR*/*; do 
    date=${dir##*/}; 
    dirname=${dir%%/*}; 
    cat $dir/Log.txt.{5..1} $dir/Log.txt > Log.txt_"${date}"_"${dirname}".txt; 
done

正如您在问题中提到的那样,这将抱怨不存在的文件,但这只是一个警告。如果您不想看到,可以重定向错误输出(尽管这也可能导致您错过合法的错误消息):

for dir in DIR*/*; do 
    date=${dir##*/}; 
    dirname=${dir%%/*}; 
    cat $dir/Log.txt.{5..1} $dir/Log.txt > Log.txt_"${date}"_"${dirname}".txt; 
done 2>/dev/null

【讨论】:

  • 谢谢!这真的很接近我需要的东西,但是文件以相反的顺序连接起来。这些文件带有时间戳,因此它们需要先与 Log.txt.2 连接,然后附加 Log.txt.1,然后附加 Log.txt。上面的命令以相反的顺序附加文件。
  • @Eliot 好的,请参阅更新的答案。但请编辑您的问题以添加此要求。
  • 完美,有效!我认为我的cat 命令的描述意味着需要以相反的顺序连接它们,但我会澄清一下。
【解决方案2】:

不像其他的那样全面,但又快又容易。随意使用findsort 输出(-zrn--zero-terminated --reverse --numeric-sort)然后使用read 对其进行迭代。

find . -type f -print0 |
sort -zrn |

while read -rd ''; do
    cat "$REPLY";
done >> log.txt

【讨论】: