使用ls查找满足条件的列表文件

时间:2018-08-24 06:00:38

标签: linux bash shell

我正在编写一个批处理程序,以删除文件名中具有条件的目录中的所有文件。

目录中有大量文本文件(〜数十万个文件),文件名固定为“ abc” +日期

abc_20180820.txt
abc_20180821.txt
abc_20180822.txt
abc_20180823.txt
abc_20180824.txt

程序尝试grep所有文件,将日期与固定日期进行比较,如果文件名的日期<固定日期,则将其删除。 但是问题是处理这么大的文件花了很长时间(删除30万个文件大约需要1个小时)。

我的问题:运行ls命令时是否可以比较日期?不在列表中获取所有文件,然后比较删除,但仅列出已满足条件的文件,然后删除。我认为这样会更好。

我的代码是

   TARGET_DATE =  "5-12"
    DEL_DATE = "20180823"   
    ls -t |  grep "[0-9]\{8\}".txt\$ > ${LIST}
        for EACH_FILE in  `cat ${LIST}` ;
        do
            DATE=`echo ${EACH_FILE} | cut -c${TARGET_DATE }`
            COMPARE=`expr "${DATE}" \< "${DEL_DATE}"`
            if [ $COMPARE -eq 1 ] ;
            then
                rm -f ${EACH_FILE}
            fi
        done 

发现了一些类似的问题,但我不知道如何解决 List file using ls with a condition and process/grep files that only whitespaces

4 个答案:

答案 0 :(得分:0)

您可以执行以下操作:

rm 201[0-7]*.txt            # remove all files from 2010-2017
rm 20180[1-4]*.txt          # remove all files from Jan-Apr 2018
# And so on
...

删除大量文件。这样您的代码就会运行得更快。

答案 1 :(得分:0)

是的,如果一个文件夹中有太多文件,则需要花费很多时间。 将这么多文件保存在一个文件夹中是个坏主意。即使是简单的ls或find也将杀死存储。而且,如果您有一些脚本可以遍历文件,则可以肯定会杀死存储。 因此,等待一小时将其清洁后。花一些时间,使文件夹结构更好。最好根据年/月/日...可能是小时对文件进行排序 例如

somefolder/2018/08/24/...files here

然后,您可以轻松删除,移动压缩文件……整月或整年。

答案 2 :(得分:0)

这是一个重构,它摆脱了讨厌的ls。在大目录上循环仍然会有些慢。

# Use lowercase for private variables
# to avoid clobbering a reserved system variable

# You can't have spaces around the equals sign
del_date="20180823"   

# No need for ls here
# No need for a temporary file
for filename in *[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9].txt
do
    # Avoid external process; use the shell's parameter substitution
    date=${filename%.txt}
    # This could fail if the file name contains literal shell metacharacters!
    date=${date#${date%?????????}}
    # Avoid expr
    if [ "$date" -lt "$del_date" ]; then
        # Just print the file name, null-terminated for xargs
        printf '%s\0' "$filename"
    fi
done |
# For efficiency, do batch delete
xargs -r0 rm

通配符扩展仍将花费相当长的时间,因为shell将对文件名列表进行排序。更好的解决方案可能是将其重构为find命令,从而避免排序。

find . -maxdepth 1 -type f \( \
      -name '*1[89][0-9][0-9][0-9][0-9][0-9][0-9].txt' \
   -o -name '*201[0-7][0-9][0-9][0-9][0-9].txt' \
   -o -name '*20180[1-7][0-9][0-9].txt ' \
   -o -name '*201808[01][0-9].txt' \
   -o -name '*2018082[0-2].txt' \
 \) -delete

答案 3 :(得分:0)

我在此线程中找到了解决方案。 https://unix.stackexchange.com/questions/199554/get-files-with-a-name-containing-a-date-value-less-than-or-equal-to-a-given-inpu

awk命令是如此强大,只花我一分钟即可处理数十万个文件(与循环相比,是1/10)。

ls | awk -v date="$DEL_DATE" '$0 <= date' | xargs rm -vrf

我什至可以用该命令以我所见过的最快答案来计数,复制和移动。

COUNT="$(ls | awk -v date="${DEL_DATE}" '$0 <= target' | xargs rm -vrf | wc -l)"