识别匹配* .X的文件,其中使用find存在* .X.Y

时间:2017-10-09 23:18:27

标签: bash

我有一个带.tif文件的目录,我通常使用find命令来识别这些文件

find . -name '*.tif'

我现在混合了.tif和.tif.mrc文件。除扩展名(file1.tiffile1.tif.mrc)外,文件名相同。我只想识别没有相应.tif个文件的.tif.mrc个文件。我可以使用find命令执行此操作吗?

5 个答案:

答案 0 :(得分:3)

test(又名[)实用程序有一堆通用测试,例如检查文件是否存在。您可以使用find

-exec条件作为find . -name '*.tif' ! -exec test -e "{}.mrc" \; -print 条件的一部分运行
(\d{3})(?:_(\w+))?

答案 1 :(得分:2)

考虑为一组文件运行一个shell命令,而不是像that other guy answer一样为每个文件运行一次。

例如:

find . -name '*.tif' -exec sh -c \
    'for file in "$@"; do [ -f "$file.mrc" ] || echo "$file"; done' \
    harbinger-of-doom {} +

代码运行sh -c '…' harbinger-of-doom加上一个或多个适合的文件名字符串。名称harbinger-of-doom是' $0'对于由sh -c运行的脚本;选择你喜欢的任何明智(或不明智)的名字。 {}指定文件名的放置位置; +表示find应该方便地将大量文件名分组到一次执行中。

实际的脚本是:

for file in "$@"; do [ -f "$file.mrc" ] || echo "$file"; done

对于每个文件名参数,测试是否存在具有.mrc扩展名的文件名,如果不存在,则打印文件名。如果您希望使用空终止文件名(与find … -print0一样),请将echo替换为printf "%s\0"。这使用内置的[(test)命令和内置的echo(或printf)命令,因此它不会调用任何子shell。这实际上是否重要有点值得商榷;性能差异不会很大,但如果要测试数百或数千个文件,性能差异可能会很大。您还可以调整文件测试 - 文件是否存在(-e),还是可读-r,还是可写(-w),或者不是空({{1} }),或......

此解决方案与Charles Duffy solution相当,并且有效等同于process substitution {{3}}。如果你的shell不支持{{3}},那么这样做有一个好处,但是当前版本的Bash确实支持它,所以它不直接相关。它确实意味着较旧的shell,或更严格的POSIX兼容的shell,如Dash,可以运行此版本。

答案 2 :(得分:2)

我不确定你有多少文件,但我曾经为大量文件做过这个,并提出了一种更有效的方法。 (我在Jonathan Leffer的回答中提醒过我):

find . -name '*.tif' -printf '[ -e %f.mrc ] || echo %f\n' | sh

这会创建一堆命令字符串来测试每个.tif是否有.mrc,例如:

[ -e file1.tif.mrc ] || echo file1.tif
[ -e foal.tif.mrc ] || echo foal.tif
[ -e fum.tif.mrc ] || echo fum.tif
...

并将这些测试直接管理到sh的单次执行,这就是为什么它比其他人的答案快〜100倍。

基准:

me               -printf | sh      400k files/second
Jonathan Leffer  -exec sh -c {} +  220k files/second
Charles Duffy    bash test          50k files/second
that other guy   -exec test          3k files/second

另外,如果你想使用它在没有mrcs的tifs上执行特定的<command>,请执行:

find . -name '*.tif' -printf '[ -e %f.mrc ] || <command> %f\n' | sh

或者,更慢但可能更容易理解(?):

find . -name '*.tif' -printf '[ -e %f.mrc ] || echo %f\n' | sh |
  while read tifpath; do
    echo "$tifpath has no .mrc"
    <command> $tifpath
  done

答案 3 :(得分:1)

或者,避免需要为每个文件调用/bin/test(以及与之相关的性能命中):

while IFS= read -r -d '' filename; do
  test -e "${filename}.mrc" || printf '%q\n' "$filename"
done < <(find . -name '*.tif' -print0)

这有点长,但效率更高,因为它能够使用shell内置版本的test(并且可以重用已有的shell,而不需要启动一个或多个新的)。

答案 4 :(得分:0)

感谢所有建议。我现在正在尝试每一个。一位同事还建议以下似乎有效

找到扩展名为.tif

的所有文件

x = $(找。-name'* .tif')

for $ in $ x;做

如果文件$ x.mrc存在,则跳过它

if [[-f $ i.mrc]]; 然后 echo跳过“$ i”; 其他 echo“处理$ i”; 科幻 完成

但是,对于扩展名稍有不同的另一组文件,即_LA.mrc,这不起作用。使用if [[-f $ i_LA.mrc]];不起作用