查找所有不存在具有不同扩展名的其他文件的文件

查找所有不存在具有不同扩展名的其他文件的文件

我想使用 find 命令来查找所有具有特定扩展名(avi)的文件,其中具有另一个扩展名(mp4)的相同文件名尚不存在。

因此考虑这些文件:

a.avi
a.mp4
c.avi

它只会导致找到文件 c.avi。

答案1

这样可以吗?

find . -name '*.avi' -type f -execdir bash -c 'f=("${0%avi}"*);((${#f[@]}==1))' {} \; -print

我将尽力解释它是如何工作的。

其实很简单:在当前目录中查找所有名称带有avi扩展名的文件。对于每个文件,假设它是X.avi目录中的文件,则执行以下execdir命令:

bash -c 'f=("${0%avi}"*);((${#f[@]}==1))' {}

{}在我们的测试用例中,其中被文件名替换X.avi。因此,这就像

bash -c 'f=("${0%avi}"*);((${#f[@]}==1))' X.avi

此时,我要强调的是,对于文件名中的空格和其他奇怪的符号,这是 100% 安全的!现在你看到 bash 将执行的代码片段了吗?我的意思是这个代码片段

f=("${0%avi}"*);((${#f[@]}==1))

它将通过将第 0 个位置参数设置为我们的文件名来执行;在我们的测试示例中它是X.avi

该部分"${0%avi}"将扩展为文件名,并avi删除尾随部分(顺便说一句,此时此文件名保证具有此扩展名),并且该部分"${0%avi}"*将扩展为当前目录(记住,包含该文件的目录)中具有扩展名的所有文件.avi。在我们的测试示例中,这就像:

X.*

然后我们用这些元素构建一个数组f,最后,bash如果f只包含一个元素(因此,在我们的测试示例中很可能f只包含一个元素X.avi),则退出此过程,否则失败。如果成功,我们将打印文件名。

答案2

具有 2 个 exec() 的解决方案:

查找 . -name '*.avi' -print | \
  perl -n -e '$x = $_; $x =~ s/\.avi\s*$/.mp4/; (-e $x) || 打印'

脚步:

  1. 这些你正在寻找的机器人
  2. 对于每个输入行/文件,测试相应的 .mp4 文件,如果未找到,则回显 .avi 文件名
    1. 将输入行复制到 $x
    2. 在 $x 中用 .mp4 替换 .avi (但仅限于行尾)
    3. 如果相应的 .mp4 文件存在,我们就完成这一行,否则打印输入行

答案3

另一种选择:查找所有.mp4.avi文件,然后从列表中删除同时存在两个扩展名的所有文件,然后删除剩余的 .mp4 文件:

find . -name '*.avi' -or -name '*.mp4' |
rev | sort -t. -k2 -k1,1 | uniq -s3 -u | grep -v '^4pm' | rev | sort

(假设没有文件名称中包含换行符。)

答案4

具有 3 个 exec() 的解决方案:

find . -name '*.avi' -print | \
  sed 's/\(.*\)\.avi$/if [ ! -f "\1.mp4" ]; then echo "\1.avi"; fi/' | \
  sh

脚步:

  1. 这些你正在寻找的机器人
  2. 删除 .avi 文件扩展名;编写一串 sh 命令,测试相应的 .mp4 文件,如果未找到,则回显 .avi 文件名
  3. 评估 sh 命令

相关内容