将一个目录中的所有文件连接到一个文件中,按修改日期排序,在Bash中

时间:2015-02-15 23:06:09

标签: linux bash

我有成千上万的纯文本格式的文章被移到一个目录中。

在标题中,有些有空格,有些有 - - 有些有单/双引号,&基本上所有其他有效的Windows& Linux文件名字符在标题中。

内容文字包含Windows& Linux行结尾(对 - 他们称之为什么?)。

在Linux / Bash中,如何将所有这些文件((一半是无扩展名,一半是.txt' s)连接到一个文件中,按修改日期排序,文件名和文件日期整齐地打印在每个文件的内容之前?

如果可以的话,请告诉我如何在嵌套文件结构中执行相同的操作,这次是为每个文件打印文件路径,除了文件名和文件。文件修改日期。

我非常感谢这一点,这是我自己写作的多年,&我一直在寻找&现在挣扎了好几个小时。我是作家,不是程序员=)

感谢您的考虑。

2 个答案:

答案 0 :(得分:1)

如果你有一些GNU好东西和dos2unix

find -type f -printf "%T@ %p\0" | sort -nz | while IFS= read -r -d '' l; do f=${l#* }; printf '%s %s\n' "$(date -r "$f")" "$f"; dos2unix < "$f"; echo; done

应该完成这项工作并对所有有趣的文件名100%安全。递归工作。对不起,这是一个很长的单行,但它是就寝时间!


修改 关于你的.fuse_hidden_blahblah文件:我不知道为什么这个文件在这里,为什么有些内容被递归添加到自身。我确信你可以通过要求find明确忽略它来安全地忽略它:

find \! -name '.fuse_hidden*' -type f -printf "%T@ %p\0" | sort -nz | while IFS= read -r -d '' l; do f=${l#* }; printf '%s %s\n' "$(date -r "$f")" "$f"; dos2unix < "$f"; echo; done

顺便说一句,内容显示在终端屏幕上。如果要将其重定向到文件mycatedfile.txt,则:

find \! -name 'mycatedfile.txt' \! -name '.fuse_hidden*' -type f -printf "%T@ %p\0" | sort -nz | while IFS= read -r -d '' l; do f=${l#* }; printf '%s %s\n' "$(date -r "$f")" "$f"; dos2unix < "$f"; echo; done > "mycatedfile.txt"

答案 1 :(得分:0)

使用this出色的答案(以避免parsing ls output之类的内容)可以获得类似这样的内容(针对单个目录):

sorthelper=();
for file in *; do
    # We need something that can easily be sorted.
    # Here, we use "<date><filename>".
    # Note that this works with any special characters in filenames

    sorthelper+=("$(stat -n -f "%Sm%N" -t "%Y%m%d%H%M%S" -- "$file")"); # Mac OS X only
    # or
    sorthelper+=("$(stat --printf "%Y    %n" -- "$file")"); # Linux only
done;

sorted=();
while read -d $'\0' elem; do
    # this strips away the first 14 characters (<date>) 
    sorted+=("${elem:14}");
done < <(printf '%s\0' "${sorthelper[@]}" | sort -z)

for file in "${sorted[@]}"; do
    if [ -f "$file" ]; then
        echo "$file";
        cat "$file";
    fi
done; > Output.txt

对于嵌套层次结构,在支持它的shell中使用for file in **; do(我很清楚bash版本4+和zsh)或将上面的内容放入函数中并在循环中的目录上递归调用它(以下代码完全未经测试)。

catall() {
    declare sorthelper=();
    for file in *; do
        # We need something that can easily be sorted.
        # Here, we use "<date><filename>".
        # Note that this works with any special characters in filenames

        sorthelper+=("$(stat -n -f "%Sm%N" -t "%Y%m%d%H%M%S" -- "$file")"); # Mac OS X only
        # or
        sorthelper+=("$(stat --printf "%Y    %n" -- "$file")"); # Linux only
    done;

    declare sorted=();
    while read -d $'\0' elem; do
        # this strips away the first 14 characters (<date>) 
        sorted+=("${elem:14}");
    done < <(printf '%s\0' "${sorthelper[@]}" | sort -z)

    for file in "${sorted[@]}"; do
        if [ -f "$file" ]; then
            echo "$file";
            cat "$file";
        elif [ -d "$file" ]; then
            catall "$file"
        fi
    done;
}

$ catall > Output.txt

编辑:正如gniourf_gniourf的优秀答案所述,我没有考虑到输入文件中不同的行结尾。在上面使用dos2unix <"$file"代替cat "$file"应该按照指示进行标准化。

再次编辑:嗯...只是注意到这并不包括输出中的修改时间。将其输入到输出中的最简单方法也是成本最高的(在输出时再次获取它),但是像gniourf_gniourf的答案中使用的解决方案也可以在这里工作(将sorthelper放到{ {1}}循环并使用最终循环中的时间戳将其写入文件中。