通过将 find 命令的输出传送到另一个 find 命令来生成文件列表?

通过将 find 命令的输出传送到另一个 find 命令来生成文件列表?

我需要生成一个文件列表,用于 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

相关内容