以下bash
脚本搜索所有目录并列出每个目录中有多少文件。
下面是我自己的 R 安装的示例输出测试 - 正是我所需要的。
find . -mindepth 6 -type d -print0 | while IFS= read -r -d '' i ; do echo -n $i": " ; ls -p "$i" | grep -v / | wc -l ; done
我的问题是,如何将此输出“files.txt”(例如)读取到另一个语句中,例如:
xargs rm -f files.txt # ("<" is missing)
读取包含所有目录的files.txt内容,并删除其中包含多个文件的目录中的所有文件(仅文件,而不是文件夹,目录结构不得更改)?
在下面的输出中,每个目录中的所有文件都将被删除,不包括 -
./R/R-3.6.1/src/library/tcltk/R/windows: 1
./R/R-3.6.1/src/library/compiler/man: 1
./R/R-3.6.1/src/library/compiler/R: 1
示例输出:
./R/R-3.6.1/src/library/tools/man: 64
./R/R-3.6.1/src/library/tools/tests: 3
./R/R-3.6.1/src/library/tools/src: 16
./R/R-3.6.1/src/library/tools/po: 23
./R/R-3.6.1/src/library/tools/R: 49
./R/R-3.6.1/src/library/tcltk: 4
./R/R-3.6.1/src/library/tcltk/man: 14
./R/R-3.6.1/src/library/tcltk/exec: 12
./R/R-3.6.1/src/library/tcltk/src: 7
./R/R-3.6.1/src/library/tcltk/po: 21
./R/R-3.6.1/src/library/tcltk/R: 6
./R/R-3.6.1/src/library/tcltk/R/unix: 2
./R/R-3.6.1/src/library/tcltk/R/windows: 1
./R/R-3.6.1/src/library/tcltk/demo: 5
./R/R-3.6.1/src/library/compiler: 4
./R/R-3.6.1/src/library/compiler/man: 1
./R/R-3.6.1/src/library/compiler/noweb: 2
./R/R-3.6.1/src/library/compiler/tests: 10
./R/R-3.6.1/src/library/compiler/po: 10
./R/R-3.6.1/src/library/compiler/R: 1
./R/R-3.6.1/src/library/graphics: 4
谢谢。
答案1
如果您想读入文件,rm
那么每一行都需要采用有意义的形式,告诉您rm
删除列出的目录中的所有文件,即
rm ./path/to/delete/*
所以....
sed -E "s|:\s[0-9]+$|/*|" files.txt
指示将文件中sed
每次出现的序列:
空白、\s
一个或多个数字[0-9]+
和行结尾替换为.$
/*
如果你按原样输入它,rm
那么它会抛出一个错误,因为你还要求它删除目录,所以,如果消息让你出错,请重定向 stderr
rm $(sed -E "s|:\s[0-9]+$|/*|" files.txt) 2>/dev/null
如果目录名称中有空格,这将失败,在这种情况下,仍然坚持将文件提供给rm
,您可以IFS
稍后更改并重置它
OFS=$IFS; IFS=$'\n'; rm $(sed -E "s|:\s[0-9]+$|/*|" files.txt) 2>/dev/null; IFS=$OFS
答案2
像这样的东西吗?
find . -type f -mindepth 6 \
| sed -r 's:/[^/]+$::' \
| sort \
| uniq -c \
| awk '$1 > 1 {print $2}' \
| xargs -i% find % -type f -delete
分解
find . -type f -mindepth 6
获取文件列表
sed -r 's:/[^/]+$::'
删除文件名,只保留目录
sort
下一个命令需要正确工作
uniq -c
计算连续的唯一行
awk '$1 > 1 {print $2}'
过滤掉只找到 1 个项目的地方,剩下的有 2 个或更多文件
xargs -i% find % -type f -delete
在每个结果目录中搜索文件并将其全部删除
通过一些后空翻和临时文件,我们可能可以避免执行xargs find
,而是获取要从输入中删除的内容列表。
答案3
由于您已经有了一种方法来检测哪些目录包含多个文件,并且结果存储在一个文件中(您称之为files.txt
),因此您可以使用 shell 脚本来完成该任务:
#!/bin/bash
IFS=":"
while read path count
do
if (( count > 1 ))
then
echo "Remove all files in $path (count = $count)"
rm "$path/"*
fi
done < files.txt