首先,请原谅我的英语不好。
我正在尝试编写一个 shell 脚本来清理备份文件夹中某些类型的文件。
我需要删除某些类型的文件,除了每个文件夹中最新的 10 个文件。
文件夹结构如下:
Root folder
│
├── folder_1
│ ├── file_1.txt
│ └── file_2.txt
│ └── file_n.txt
│
├── folder_2
│ ├── file_1.txt
│ └── file_2.txt
│ └── file_n.txt
│
├── folder_n
│ ├── file_1.txt
│ └── file_2.txt
│ └── file_n.txt
│
我使用了来自大卫·福斯特作为基础,但无法弄清楚如何使其在不同的文件夹中分别工作,而无需在脚本中手动写入每个文件夹名称。
目前,脚本如下所示:
find /volume1/rootfolder/ -type f -name *.txt -printf '%T@ %p\0' |
sort --zero-terminated --reverse --numeric-sort --field-separator=' ' --key 1,1 |
gawk -F ' ' -v RS='\0' -v ORS='\0' -v retain_count=10 \
'BEGIN{ maxage = systime() - retain_younger_days * 24 * 3600; }
(NR > retain_count) && (int($1) < maxage) { print(substr($0, length($1) + 2)); }' |
xargs -r0 -- rm --
但问题是,它会删除所有文件夹中的所有文件,只保留最新的 10 个文件。因此,总的来说,所有文件夹中只有 10 个文件,而不是每个文件夹中都有 10 个文件。
请帮我弄清楚如何编写脚本来分别处理每个文件夹。
答案1
你将其分为两部分。首先,你构建一个目录结构,在这种情况下,我们只需要包含文件的目录。在第二部分中,我们首先对最新文件进行排序,并跳过带有 的文件tail
。
#!/bin/bash
while IFS= read -rd ''; do
find "$REPLY" \
-maxdepth 1 -type f -name '*.txt' -printf '%T@\t%p\0' | sort -zk1rn | cut -zf2- | tail -zn +$((10+1)) | xargs -r -0 echo rm
done < <( \
find $PWD/data \
-mindepth 2 -type f -printf %h\\0 | sort -zu \
)
也可以globstar
使用for-loop
:
#!/bin/bash
shopt -s globstar nullglob
for a in data/*/**/; do
find "$a" \
-maxdepth 1 -type f -name '*.txt' -printf '%T@\t%p\0' | sort -zk1rn | cut -zf2- | tail -zn +$((10+1)) | xargs -r -0 echo rm
done
最后,我们利用计数器数组来跟踪文件数量:
#!/bin/bash
find $PWD/data -mindepth 1 -type f -name '*.txt' -printf '%T@\t%p\0' \
| sort -zk1rn | cut -zf2- \
| awk -F / -vRS='\0' -vORS='\0' '{a=$0; NF=NF-1} b[$0]++ >= 10 {print a}' | xargs -r -0 echo rm