如果我在目录中有一组如下命名的图像:
filename.jpg
filename.jpg.webp
filename-150x150.jpg
filename-250x250.jpg
filename-250x250.jpg.webp
filename-600x600.jpg
filename-800x800.jpg
filename-800x800.jpg.webp
有没有办法使用find
命令(或其他命令)返回每个没有版本的文件.webp
?因此在本例中它将返回 150x150 和 600x600 文件。
答案1
如果您计划使用以下任何各种变体找到的文件名,请确保您不解析输出中的文件名。反而,将 替换printf
为您需要执行的任何操作。这样,您就可以避免包含空格和通配符等文件名的问题。它还会使您的代码更加高效和美观,并最终带来更健康的生活方式和更好的朋友。
我所做的一个假设是,您想要查找没有对应.webp
文件的 JPEG 图像,因为您想要创建这些.webp
文件。这就是为什么我在下面使用-e
(“名称存在”) 测试,而不是-f
(“名称存在并且是常规文件或指向此类文件的符号链接”) 或-r
(“名称存在并且可读”) 测试。
如果.webp
名字存在,如果它是目录或字符特殊文件或其他一些非常规文件类型(测试-f
将是错误的),或者如果它不可读(测试-r
将是错误的),那么创建该文件就会出现问题,.webp
因为它会覆盖现有的内容,或者被放入目录中,或者导致权限错误,具体取决于该.webp
文件的创建方式。
使用一个简单的循环来迭代匹配的名称*.jpg
并打印出那些与文件不对应的名称*.jpg.webp
:
for name in *.jpg; do
[ -f "$name" ] && [ ! -e "$name.webp" ] && printf '%s\n' "$name"
done
要将名称保存在列表中,我们可以使用位置参数列表:
set --
for name in *.jpg; do
[ -f "$name" ] && [ ! -e "$name.webp" ] && set -- "$@" "$name"
done
printf 'Needs webp fixed: %s\n' "$@"
在 中bash
,您可能希望将名称保存在命名数组中:
needs_webp=()
for name in *.jpg; do
[ -f "$name" ] && [ ! -e "$name.webp" ] && needs_webp+=( "$name" )
done
printf 'Needs webp fixed: %s\n' "${needs_webp[@]}"
在shell 中,您可以在通配本身中zsh
对名称进行测试:*.webp
printf 'Needs webp fixed: %s\n' *.jpg(.e['[ ! -e $REPLY.webp ]'])
在这里,.
模式末尾的 in 通配限定符确保仅匹配常规文件(而不是目录等),并且e['[ ! -e $REPLY.webp ]']
充当测试以查看当前名称 是否$REPLY
应包含在结果列表中。
和find
:
find . -name '*.jpg' -type f ! -exec test -e {}.webp \; -print
这会在当前目录或下面的目录中查找名称与模式匹配的任何常规文件*.jpg
,如果没有与相同名称相对应但.webp
添加到末尾的文件,则打印该名称。
{}
但是,如果 POSIX 标准与其他字符串连接(如上面所示),则 POSIX 标准不保证将其替换为当前文件名。所以如果你想确定它会起作用,你会说
find . -name '*.jpg' -type f -exec sh -c '
for name do
[ -e "$name.webp" ] && printf "%s\n" "$name"
done' {} +
正如您所看到的,现在我们或多或少回到了这个答案的第一个循环。现在唯一的区别是find
从当前目录或其任何子目录递归地为其提供现有路径名。
答案2
这对我有用:
find . -not -name '*.webp' -exec test ! -r {}.webp \; -exec echo {} \;
它查找所有不以 结尾的名称.webp
。对于找到的每个名称,它都会测试是否.webp
存在具有相同名称和扩展名的文件。如果没有,则打印该文件。
值得注意的是,第二个-exec
仅在第一个成功返回时才执行,即仅当相应的.webp
扩展名文件不存在时。
在您的文件列表上运行,我的输出是
./filename-600x600.jpg
./filename-150x150.jpg
答案3
用循环试试这个:
# to expand to null string in empty directories¹
shopt -s nullglob
# loop over the jpg files
for i in *.jpg; do
# test if there's a file that matches the name but with '.webp' extension
# if there's a match don't do anything and continue with the loop
[[ -f "$i.webp" ]] && continue || \
# else perform an operation
echo "$i"
done
filename-150x150.jpg
filename-600x600.jpg
空球 如果设置,Bash 允许不匹配文件的文件名模式扩展
为空字符串,而不是它们本身。