使用“find”而不是“for-do-done”来搜索子目录

使用“find”而不是“for-do-done”来搜索子目录

在 OS X 10.8 中,我有几个包含图片的文件夹,但并非所有文件都有正确的扩展名,有些 GIF 被命名为 JPG 等等。

我有一个可以完成实际目录工作的单行程序:

for f in * ; do type=$(file "$f" | tr "[A-Z]" "[a-z]" | awk '{print $2}') ; mv "$f" "${f%.*}.$type" ; done

现在我想使用“查找”来搜索子文件夹但总是失败。

有什么提示吗?

答案1

在这种情况下,您可以轻松找到与扩展名 .jpg 不匹配的文件:

find . -type f -not "*.jpg"

您还可以循环检查结果并检查文件是否确实是 jpg:

find . -type f -not "*.jpg" | while read fname; do
  if [[ $(file $fname) == *"JPG"*]]
    then echo $fname
  fi
done

答案2

最简单的方法是启用文件的递归通配符,例如在 Bash 中:

shopt -s globstar
for f in **/*.*; do
    type=$(file "$f" | tr "[A-Z]" "[a-z]" | awk '{print $2}')
    mv -- "$f" "${f%.*}.$type"
done

这样就不必解析find输出。问题是,如果文件太多,此命令可能会失败,因为它可能超出命令行的最大大小。这是因为**/*.*在执行命令之前,Bash 会扩展 中的文件名。

因此,另一种方法是使用find,将其输出通过管道传输到whileread

find . -type f -print0 | while IFS= read -r -d '' f
    type=$(file "$f" | tr "[A-Z]" "[a-z]" | awk '{print $2}')
    mv -- "$f" "${f%.*}.$type"
done

有关使用文件列表的一些最佳实践,请参阅:http://mywiki.wooledge.org/ParsingLs

答案3

我发现这种方法对我来说很有效,但它并不是很优雅:-P

find . -type f -name "*.*" -exec sh -c 'name=$(basename {} | cut -d. -f1) ; type=$(file {} | tr "[A-Z]" "[a-z]" | cut -d" " -f2) ; mv `basename {}` "$name.$type"' \;

答案4

根据前面的评论,我猜您正在寻找一种不循环遍历结果的方式来解析结果,只需使用 find:

find . -type f -not "*.jpg" -exec sh -c "if [[ $(file {}) == *'JPG'* ]] then; echo {}; fi" \;

相关内容