使用下面的代码过滤图像时,我还需要过滤文件。
例如,IMG_0079.JPG.JPG,当运行下面的代码时,它允许.JPG
过滤掉附加的文件,我似乎无法发现为什么?
检查输入是否正确
if [ $# != 2 ]; then echo "Usage: phar image_path archive_path" && exit; fi
如果目标目录不存在,这将创建一个
mkdir -p $2
查找、复制并向文件添加必要后缀的语句
find $1 -iname IMG_[0-9][0-9][0-9][0-9].JPG -exec cp -b --suffix=.JPG {} $2 \; echo complete!
检查并删除重复的语句。它将比较每个文件的 md5。
shopt -s nullglob for file in "$2"/* do md5sum=$(md5sum < "$file") echo "-- Found: $file ($md5sum)" for duplicate in "$2"/* #loop to find/remove duplicates do [ "$file" = "$duplicate" ] && continue #comparison of 2 files [ "$md5sum" = "$(md5sum < "$duplicate")" ] && rm -v "$duplicate" #removal of duplicates done done
答案1
如果我理解正确的话,你的问题就在于此:
find $1 -iname IMG_[0-9][0-9][0-9][0-9].JPG
这.JPG.JPG
从一开始就找不到文件。看:
mkdir JPG
for n in 9 8 7 6 5 4 3 2 1
do touch ./JPG/IMG_000${n}.JPG
done
find ./JPG -iname IMG_[0-9][0-9][0-9][0-9].JPG
###OUTPUT###
./JPG/IMG_0001.JPG
./JPG/IMG_0002.JPG
./JPG/IMG_0003.JPG
./JPG/IMG_0004.JPG
./JPG/IMG_0005.JPG
./JPG/IMG_0006.JPG
./JPG/IMG_0007.JPG
./JPG/IMG_0008.JPG
./JPG/IMG_0009.JPG
所以现在我要...
for f in ./JPG/* ; do touch ${f}.JPG ; done && ls ./JPG
IMG_0001.JPG IMG_0003.JPG.JPG IMG_0006.JPG IMG_0008.JPG.JPG
IMG_0001.JPG.JPG IMG_0004.JPG IMG_0006.JPG.JPG IMG_0009.JPG
IMG_0002.JPG IMG_0004.JPG.JPG IMG_0007.JPG IMG_0009.JPG.JPG
IMG_0002.JPG.JPG IMG_0005.JPG IMG_0007.JPG.JPG
IMG_0003.JPG IMG_0005.JPG.JPG IMG_0008.JPG
让我们看看find
现在向我们展示了什么:
find ./JPG -iname IMG_[0-9][0-9][0-9][0-9].JPG
###OUTPUT###
./JPG/IMG_0001.JPG
./JPG/IMG_0002.JPG
./JPG/IMG_0003.JPG
./JPG/IMG_0004.JPG
./JPG/IMG_0005.JPG
./JPG/IMG_0006.JPG
./JPG/IMG_0007.JPG
./JPG/IMG_0008.JPG
./JPG/IMG_0009.JPG
所以你看,因为我的.JPG.JPG
文件名不以字符串结尾,所以[0-9]{4}.JPG
find
它们一开始就不会显示出来。\*
在该搜索字符串的末尾添加 a-iname
可能更适合您。
不过,正如另一个答案提到的,另一个问题是你的外壳球。例如:
sh -cx 'cd ./JPG ; find . -iname IMG_[0-9][0-9][0-9][0-9].JPG'
+ cd ./JPG
+ find . -iname IMG_0001.JPG IMG_0002.JPG IMG_0003.JPG IMG_0004.JPG IMG_0005.JPG IMG_0006.JPG IMG_0007.JPG IMG_0008.JPG IMG_0009.JPG
find: paths must precede expression: IMG_0002.JPG
Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]
你看?如果 shell 可以,它会[glob]
在您将命令字符串传递给 之前得到的那些不带引号的方括号中find
。它可能看起来应该更像这样:
find "$1" -iname 'IMG_[0-9][0-9][0-9][0-9].JPG*'
关于最后一点,您可能不需要那么多递归循环。我认为 - 只要你只想删除旧的cp --suffix=.JPG -b
ackups - 这可能可以作为所有内容的可行替代品shopt...
:
( dir=$2
set -- "${dir}"/*[0-9].???
while [ -e "$1" ]
do cmp "$1" "${1}.JPG" &&
rm -v "${1}.JPG" 2>&1
shift ; done
) 2>/dev/null
不过,不可否认,这可以通过一个方法进行很大程度的优化有点递归循环如:
( dir=$2
set -- "${dir}"/*[0-9].???
while [ -e "$1" ]
do until [ -e "${1}.JPG" ]
do shift || break; done
cmp "$1" "${1}.JPG" &&
rm -v "${1}.JPG" 2>&1
${1+shift} ; done
) 2>/dev/null
我说有点因为while
和until
循环都在相同的参数集上运行,甚至从不测试同一个文件两次,所以它们并不完全一样递归即使它们是嵌套的。无论如何,优化在于不需要exec
任何其他过程until
,并且尽可能仅依赖 shell 内置函数。
答案2
for
你提到的循环给我抛出了一个错误。但当我对方括号使用转义字符时,它工作得很好。所以我的 for 循环会是这样的:
find $1 -iname IMG_\\[0-9\\]\\[0-9\\]\\[0-9\\]\\[0-9\\].JPG -exec cp -b --suffix=.JPG {} $2 \;