find . -maxdepth 1 -type f -exec identify -regard-warnings -verbose {} > /dev/null 2>&1 + || mv "$1" --backup=numbered {} -t "./Corrupted"
我正在尝试使用上述方法检查当前目录中是否存在损坏的 JPEG 图像,如果存在,则将它们移动到另一个目录。
据我所知,到目前为止的问题是逻辑根本不起作用——||
当identify以非零错误代码退出时,运算符右边的任何内容都不会执行,即使我使用简单的进行测试|| echo "File is bad"
。
我知道如果第一个谓词为真,我可以使用第二个-exec
谓词来执行命令,但如果结果是假,-exec
有没有办法执行命令?-exec
答案1
您可以执行 a bash -c
,例如:
find [other parm] -exec bash -c 'identify -regard-warnings -verbose "$1" || exit 0 ; exit 1' onTheFlyScript {} \; -exec mv {} ./Corrupted \;
慢动作:
identify -regard-warnings -verbose "$1" || exit 0 ; exit 1
反转输出逻辑identify
(如果错误则为 0)-exec bash -c '...' onTheFlyScript {} \;
设置$0
为“onTheFlyScript”(除非有错误,否则忽略)并$1
设置为您的文件,因此如果文件损坏,它会成功(rc=0)-exec mv {} ./Corrupted \;
如果第一个 exec 成功则执行,因此如果文件损坏
identify
考虑到好文件的输出,我会-verbose
在这里避免使用 parm,它只会减慢进程。
编辑:更简单的版本,不需要bash -c
(在更复杂的情况下仍然是不可避免的):
find . -maxdepth 1 -name '*.jpg' \( -exec identify -quiet {} \; -o -exec mv -t ./Corrupted {} \+ \)
换句话说,-exec
当第一个失败时,将执行第二个。
正如卡米尔 (Kamil) 在评论中所说,你无法大规模识别文件,因为你需要每个文件的状态,但你确实可以将 a;
和 a结合起来+
,第二个确实是使用尽可能多的参数执行的。
答案2
我终于设法找出了卡米尔和异种{}
这确实有效。我主要通过将to 移到选项之前来实现这一点-t
,尽管使用exec... +
语法这也会导致以下错误:
发现:缺少“-exec”参数
因此我还必须切换到使用exec... \;
语法,最终得到以下工作命令:
find . -maxdepth 1 -type f -iname "*.jpg" ! -exec identify -regard-warnings -verbose > /dev/null {} \; -exec mv {} -t ./Corrupted \;
需要切换-regard-warnings
到identify
以确保警告除了错误之外还以非零值退出(这对于移动仅标记警告的损坏图像是必要的),并且-verbose
需要切换到 将警告和错误打印到屏幕上。如果您根本不想看到任何输出,则可以省略-verbose
。
答案3
对于简单的命令来说,使用起来find -exec
很容易。但我认为对于更高级的东西,最好通过管道传输| while read var; do ...cmd1 $var; cmd2 "$var"; cmd3;...stuff...; done
:
find . -maxdepth 1 -type f | while read f; do identify "$f" > /dev/null 2>&1 || mv --backup=numbered "$f" ./Corrupted; done
答案4
尝试使用括号:
(find . -maxdepth 1 -type f -exec identify -regard-warnings -verbose {} > /dev/null 2>&1 +) || mv "$1" --backup=numbered {} -t "./Corrupted"