Linux - 列出并删除名称包含特定模式的多个不同文件

Linux - 列出并删除名称包含特定模式的多个不同文件

我有多个文件夹,其中包含使用 Windows 文件历史记录创建的文件和文件夹。文件名都具有相同的结构,例如 -Super secret document (YYYY_MM_DD HH_MM_SS UTC).ext

例如文件文件夹看起来像这样:

...
Default (2020_10_28 06_34_32 UTC).rdp
Default (2020_10_29 06_43_49 UTC).rdp
Default (2020_11_02 06_45_18 UTC).rdp
desktop (2019_10_03 12_32_29 UTC).ini
desktop (2019_11_13 10_57_26 UTC).ini
desktop (2019_12_11 16_12_56 UTC).ini
...
Copy of 2019 (2019_08_03 12_32_29 UTC).xlsx'
Copy of 2019 (2019_10_03 12_32_29 UTC).xlsx'
VW (2020_09_08 12_12_20 UTC).docx
VW (2020_09_08 14_27_50 UTC).docx
Min20071007510 (2020_07_10 05_56_02 UTC).pdf
Min20071007510 (2020_07_11 05_56_02 UTC).pdf
...

通过使用此命令,find我可以过滤具有指定结构的文件:

find * -type f -name "*\ (*_*_*\ *_*_*\ UTC).*"

我在尝试着消除除了每个文件的最新副本之外的所有单独文件,我不知道如何才能做到这一点。

谢谢!

答案1

#!/bin/bash

# Get a list of files
files=$(find . name "*.dat" | sort -r)

lastfile=""
IFS=$'\n'
for filename in $files
do
        parts=( $(grep -Eo '.* |\(.*\)' <<< "$filename") )

        # Get the first part of the file name
        filepart="${parts[0]}"

        # If this is a new set of files, this is the file kept.
        if [ "$filepart" != "$lastfile" ]
        then
                echo "Keeping $filename"
        else
                echo "Removing $filename"
                rm $filename
        fi
        lastfile=$filepart
done

此处使用两步过程。

首先,我们获得所有文件的列表。这就是find命令。您将需要修改文件集的模式,find /path/如果您想选择文件目录,则可能会这样。该列表是反向排序的。这使得具有最近(最新)日期的模式成为第一个。

现在我们有了列表,我们想循环遍历它。只要文件名的第一部分匹配,我们就会保留第一个文件。 grep将文件名分为两部分:名称和日期代码。它要求名称用空格分隔,日期代码用括号分隔。这将构成变量parts。将文件的第一部分与最后一部分进行比较将告诉您是否处于一组新数据中。请记住:列表是经过排序的,因此只有当文件名的第一部分发生变化时才会发生这种情况。

可能还有更雄辩的解决方案,其他人可以添加评论——我是bash脚本专家,但绝不是大师。

答案2

我在 ChatGPT 的帮助下成功解决了我的问题(我知道,我很懒)

以下脚本递归地执行基于 Windows 文件历史记录的备份并删除除最新副本之外的所有文件副本:

#!/bin/bash

declare -A latest_files

# Find all files in the current directory and its subdirectories
find . -type f -print0 | while IFS= read -r -d '' file; do
    # Check if the file has a date in the format (YYYY_MM_DD HH_mm_ss UTC)
    if [[ $file =~ \(([0-9]{4}_[0-9]{2}_[0-9]{2} [0-9]{2}_[0-9]{2}_[0-9]{2} UTC)\) ]]; then
        date_match="${BASH_REMATCH[1]}"
        # Extract the base filename (excluding the date and extension)
        base_filename="${file%% (*}.${file##*.}"

        # If the date is greater than the stored date for the same full filename or if the filename is not stored
        if [[ "${latest_files[$file]}" < "$date_match" || -z "${latest_files[$file]}" ]]; then
            # Keep the latest version of the file
            latest_files["$file"]="$date_match"

            # Remove the older versions with the same full filename
            for old_file in "${!latest_files[@]}"; do
                if [[ "$old_file" != "$file" && "${old_file%% (*}" == "${file%% (*}" && "${latest_files[$old_file]}" != "$date_match" ]]; then
                    rm -f "$old_file"
                fi
            done
        else
            # Remove this version as it's older
            rm -f "$file"
        fi
    fi
done

答案3

您可以使用正则表达式寻找命令。对于您的特定情况,命令将类似于: find /path/to/backup/ -type f -regextype posix-extended ! -regex '.*_backup_[0-9]+\.ext' -delete

希望它有用!

相关内容