我有一个带.tif文件的目录,我通常使用find
命令来识别这些文件
find . -name '*.tif'
我现在混合了.tif和.tif.mrc文件。除扩展名(file1.tif
和file1.tif.mrc
)外,文件名相同。我只想识别没有相应.tif
个文件的.tif.mrc
个文件。我可以使用find
命令执行此操作吗?
答案 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)
感谢所有建议。我现在正在尝试每一个。一位同事还建议以下似乎有效
x = $(找。-name'* .tif')
for $ in $ x;做
if [[-f $ i.mrc]]; 然后 echo跳过“$ i”; 其他 echo“处理$ i”; 科幻 完成
但是,对于扩展名稍有不同的另一组文件,即_LA.mrc,这不起作用。使用if [[-f $ i_LA.mrc]];不起作用