我需要生成一个文件列表,用于 shell 脚本。该列表应为所有硬链接的文件(在指定的目录中)。我想用符号链接替换硬链接。
(显然,我无法删除最后一个硬链接。这个问题与另一个问题它有一个致命的缺陷。
我愿意听取任何关于如何做到这一点的建议。如果你认为这个问题是重复的,请确保其他答案确实作品。我还没有找到满足这些要求的可行解决方案。
- 查找可能包含要保留的硬链接文件的目录
- 从顶级目录或文件系统根目录搜索其他硬链接文件
- 两个目录都可以作为参数提供
- 也可以仅对指定类型的文件起作用(例如图像)
我的(新)想法是通过管道输出这个find
find "$dir" -type f -links +1
进入这个:
find "$topdir" -xdev -samefile <output from other find> -printf '%i:%p\n' | sort --field-separator=:
如果可行,那么我将把结果列表提供给与此类似的 while 循环(来自原始代码):
last_inode=
while IFS= read -r path_info
do
inode=${path_info%%:*}
path=${path_info##*:}
if [[ $last_inode != $inode ]]; then
printf "$inode\n"
last_inode=$inode
path_to_keep=$path
else
rm -- "$path"
ln -s -- "$path_to_keep" "$path"
fi
done
我还可以像-iname "*.jpg"
(第一个) find 命令一样添加一个参数,以便仅对 JPEG 文件起作用。(我也愿意接受更好的建议。)
答案1
这是一个可行的解决方案。我对其进行了相当广泛的测试。但是,我欢迎更好的答案。我宁愿选择别人的答案,而不是我自己的答案(这说明我对我的 bash 脚本技能很有信心)。
find "$dir" -type f -links +1 -exec find "$topdir" -xdev -samefile '{}' -printf '%i:%p\n' \; | sort --field-separator=:
这是整个解决方案,扩展了链接的问题(假设它有效):
#!/bin/bash
set -o nounset
topdir='/'
dir='/MotherBoards/Tyan S2720 Thunder i7500/IntelNetworkAdapterDrivers/Setup/'
echo "starting..."
# For each path which has multiple links
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# (except ones containing newline)
last_inode=
while IFS= read -r path_info
do
inode=${path_info%%:*}
path=${path_info##*:}
if [[ $last_inode != $inode ]]; then
printf "$inode\n"
last_inode=$inode
path_to_keep=$path
else
printf "$inode\tln -s\t'$path_to_keep'\t'$path'\n"
rm -- "$path"
ln -s -- "$path_to_keep" "$path"
fi
done < <( find "$dir" -type f -links +1 -exec find "$topdir" -xdev -samefile '{}' -printf '%i:%p\n' \; | sort --field-separator=: )
# Warn about any excluded files
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
buf=$( find "$dir" -type f -links +1 -wholename '*
*' )
if [[ $buf != '' ]]; then
echo 'Some files not processed because their paths contained newline(s):'$'\n'"$buf"
fi
echo "finished"
exit 0