我有以下目录结构。我需要找到存在名为 的文件的目录log.xml
,并完全删除所有目录,除了特定符号链接指向的目录之外。
例如,/dir1/main/app1/v004/
和/dir1/main/app2/v004/log.xml
由符号链接指向,因此不应删除它们。
另外,如何删除除符号链接指向之外的目录,而无需找到log.xml
.
您能帮忙提供正确的解决方案吗?
/dir1/main/app1/v001/
/dir1/main/app1/v002/log.xml
/dir1/main/app1/v003/log.xml
/dir1/main/app1/v004/log.xml
/dir1/main/app1/v005/log.xml
/dir1/ln1/app -> /dir1/main/app2/v004
/dir1/main/app2/v001/
/dir1/main/app2/v002/log.xml
/dir1/main/app2/v003/log.xml
/dir1/main/app2/v004/log.xml
/dir1/main/app2/v005/log.xml
/dir1/ln2/app -> /dir1/main/app2/v004
答案1
app
假设您要删除目录中除v001
(不包含log.xml
) 和v004
(符号链接指向的)之外的所有子目录:
for topdir in /dir1 /dir2; do
for dirpath in "$topdir"/main/app/*/; do
if [ -e "$dirpath/log.xml" ] && ! [ "$dirpath" -ef "$topdir"/ln/app ]
then
printf 'Would remove "%s"\n' "$dirpath"
# rm -rf "$dirpath"
fi
done
done
外部循环用于循环遍历两个最顶层的目录/dir1
(/dir2
您可能希望将/dir[12]
其用作通配模式)。顶级目录的名称保存在topdir
变量中。
内循环迭代下面的子目录app
,underlying $topdir
。如果子目录包含名为log.xml
(第一个测试, with -e
)的内容,并且符号链接未指向该目录"$topdir"/ln/app
(第二个测试, with -ef
),则可以将其删除。
该-e
测试是对给定路径名是否存在的标准测试。该-ef
测试是非标准的,但由bash
shell 实现,它在解析符号链接后测试两个路径名是否引用同一文件(或本例中的目录)。
为了安全起见,实际删除已被注释掉。在启用该命令之前,您应该对之前备份的数据进行测试rm
。
要删除子目录,无论它们是否包含名为 的内容log.xml
,请删除-e
测试,以便if
语句看起来像
if ! [ "$dirpath" -ef "$topdir"/ln/app ]; then
printf 'Would remove "%s"\n' "$dirpath"
# rm -rf "$dirpath"
fi
答案2
GNUfind
有一个选项-samefile
,您需要包含 -L 选项才能使其工作。
看一下下面两个命令的输出
(cd /dir1 ; find -L . -samefile ln/app ) # your file and link
(cd /dir1 ; find -L . -not -samefile ln/app ) # everything other than your file and link
第二个应该生成您要删除的文件的列表。也许您只想列出文件而不是目录,如果是这样,那么只需添加-type f
find -L . -type f -samefile ln/app)
删除文件很简单,只需在 find 命令后附加一个 exec 操作,例如-exec rm -v {} \;