删除除最后一场比赛以外的所有比赛
delete all but the last match
我想删除目录中每个文件夹中存在的与 file*
匹配的一组文件中除最后一个匹配项之外的所有文件。
例如:
Folder 1
file
file_1-1
file_1-2
file_2-1
stuff.txt
stuff
Folder 2
file_1-1
file_1-2
file_1-3
file_2-1
file_2-2
stuff.txt
Folder 3
...
等等。在每个子文件夹中,我只想保留最后一个匹配的文件,因此对于 Folder 1
这将是 file_2-1
,在 Folder 2
中它将是 file_2-2
。每个子文件夹中的文件数量通常不同。
因为我有一个非常嵌套的文件夹结构,所以我考虑过像这样使用 find
命令
find . -type f -name "file*" -delete_all_but_last_match
我知道如何删除所有匹配但不知道如何排除最后一个匹配。
我还找到了下面这段代码:
https://askubuntu.com/questions/1139051/how-to-delete-all-but-x-last-items-from-find
但是当我将修改后的版本应用到测试文件夹时
find . -type f -name "file*" -print0 | head -zn-1 | xargs -0 rm -rf
它在大多数情况下会删除所有匹配项,只有在某些情况下会保留最后一个文件。所以它对我不起作用,大概是因为每个文件夹中的文件数量不同。
编辑:
这些文件夹不包含更多的子文件夹,但它们通常位于几个子文件夹级别的末尾。因此,如果脚本也可以在上面的某些级别执行,那将是一个好处。
尝试使用 awk 和 xargs 的以下解决方案:
find . -type f -name "file*" | awk -F/ '{ map1[$(NF-1)]++;map[$(NF-1)][map1[$(NF-1)]]=[=10=] }END { for ( i in map ) { for (j=1;j<=(map1[i]-1);j++) { print "\""map[i][j]"\"" } } }' | xargs rm
解释:
find . -type f -name "file*" | awk -F/ '{ # Set the field delimiter to "/" in awk
map1[$(NF-1)]++; # Create an array map1 with the sub-directory as the index and an incrementing counter the value (number of files in each sub-directory)
map[$(NF-1)][map1[$(NF-1)]]=[=11=] # Create a two dimentional array with the sub directory index one and the file count the second. The line the value
}
END {
for ( i in map ) {
for (j=1;j<=(map1[i]-1);j++) {
print "\""map[i][j]"\"" # Loop through the map array utilising map1 to get the last but one file and printing the results
}
}
}' | xargs rm # Run the result through xargs rm
删除 xargs 的管道以验证文件是否按预期列出,然后再重新添加以实际删除文件。
#!/bin/bash
shopt -s globstar
for dir in **/; do
files=("$dir"file*)
unset 'files[-1]'
rm "${files[@]}"
done
我想删除目录中每个文件夹中存在的与 file*
匹配的一组文件中除最后一个匹配项之外的所有文件。
例如:
Folder 1
file
file_1-1
file_1-2
file_2-1
stuff.txt
stuff
Folder 2
file_1-1
file_1-2
file_1-3
file_2-1
file_2-2
stuff.txt
Folder 3
...
等等。在每个子文件夹中,我只想保留最后一个匹配的文件,因此对于 Folder 1
这将是 file_2-1
,在 Folder 2
中它将是 file_2-2
。每个子文件夹中的文件数量通常不同。
因为我有一个非常嵌套的文件夹结构,所以我考虑过像这样使用 find
命令
find . -type f -name "file*" -delete_all_but_last_match
我知道如何删除所有匹配但不知道如何排除最后一个匹配。
我还找到了下面这段代码:
https://askubuntu.com/questions/1139051/how-to-delete-all-but-x-last-items-from-find
但是当我将修改后的版本应用到测试文件夹时
find . -type f -name "file*" -print0 | head -zn-1 | xargs -0 rm -rf
它在大多数情况下会删除所有匹配项,只有在某些情况下会保留最后一个文件。所以它对我不起作用,大概是因为每个文件夹中的文件数量不同。
编辑:
这些文件夹不包含更多的子文件夹,但它们通常位于几个子文件夹级别的末尾。因此,如果脚本也可以在上面的某些级别执行,那将是一个好处。
尝试使用 awk 和 xargs 的以下解决方案:
find . -type f -name "file*" | awk -F/ '{ map1[$(NF-1)]++;map[$(NF-1)][map1[$(NF-1)]]=[=10=] }END { for ( i in map ) { for (j=1;j<=(map1[i]-1);j++) { print "\""map[i][j]"\"" } } }' | xargs rm
解释:
find . -type f -name "file*" | awk -F/ '{ # Set the field delimiter to "/" in awk
map1[$(NF-1)]++; # Create an array map1 with the sub-directory as the index and an incrementing counter the value (number of files in each sub-directory)
map[$(NF-1)][map1[$(NF-1)]]=[=11=] # Create a two dimentional array with the sub directory index one and the file count the second. The line the value
}
END {
for ( i in map ) {
for (j=1;j<=(map1[i]-1);j++) {
print "\""map[i][j]"\"" # Loop through the map array utilising map1 to get the last but one file and printing the results
}
}
}' | xargs rm # Run the result through xargs rm
删除 xargs 的管道以验证文件是否按预期列出,然后再重新添加以实际删除文件。
#!/bin/bash
shopt -s globstar
for dir in **/; do
files=("$dir"file*)
unset 'files[-1]'
rm "${files[@]}"
done