按名称递归比较目录内容,忽略文件扩展名

按名称递归比较目录内容,忽略文件扩展名

我有一个包含大约 7,000 个音乐文件的目录。我使用lame将其中的所有文件递归地重新编码到一个单独的目录中,输出具有相同相对路径和文件名的所有文件。输出文件具有 .mp3 扩展名,但某些输入文件具有不同的扩展名(.wma、.aac 等)。

我可以看到输出目录中缺少约 100 个文件的文件计数差异。我想要做的是对两个目录进行比较,并获取源中存在但目标中不存在的文件列表。这很简单,除了我需要忽略文件扩展名的差异。

我尝试过在打开dry-run的情况下使用rsync,但我无法找到忽略文件扩展名的方法。我也尝试过 diff 但无法找到仅按名称检查但忽略文件扩展名的选项。我开始认为我可以在两个目录上执行递归 ls,删除文件扩展名,然后比较输出,但我真的不知道从哪里开始使用 sed 或 awk 修改 ls 输出。

答案1

要查看列表,这里有两种变体,一种递归到子目录,另一种不递归。所有这些都使用特定于 bash、ksh 和 zsh 的语法。

comm -3 <(cd source && find -type f | sed 's/\.[^.]*$//' | sort) \
        <(cd dest && find -type f | sed 's/\.[^.]*$//' | sort)
comm -3 <(cd source && for x in *; do printf '%s\n' "${x%.*}"; done | sort) \
        <(cd dest && for x in *; do printf '%s\n' "${x%.*}"; done | sort)

更短,在 zsh 中:

comm -3 <(cd source && print -lr **/*(:r)) <(cd dest && print -lr **/*(:r))
comm -3 <(print -lr source/*(:t:r)) <(print -lr dest/*(:t:r))

comm命令列出两个文件 ( ) 共有的行comm -12、仅在第一个文件 ( comm -23) 中或仅在第二个文件 ( comm -13) 中的行。这些数字表示从输出中减去的内容。两个输入文件必须排序。

在这里,文件实际上是命令的输出。 shell<(…)通过提供一个“假”文件(FIFO 或/dev/fd/命名文件描述符)作为命令的参数来评估该构造。

1 所以这里减去说者是完全有道理的。


如果您想对文件执行操作,您可能需要迭代源文件。

cd source
for x in *; do
  set -- "…/dest/${x%.*}".*
  if [ $# -eq 1 ] && ! [ -e "$1" ]; then
    echo "$x has not been converted"
  elif [ $# -gt 1 ]; then
    echo "$x has been converted to more than one output file: " "$@"
  else
    echo "$x has been converted to $1"
  fi
done

相关内容