尝试在 Linux 控制台中获取脚本以显示重复的文件名而不是错误

尝试在 Linux 控制台中获取脚本以显示重复的文件名而不是错误

我正在尝试编写一个将在Linux环境中运行的脚本。

.jpeg它将在目录树中查找文件,然后将它们复制到名为 的目录中jpegs

我想让它向我显示重复的文件名,但只在生成的列表中列出一次重复的文件名(因此它不会显示相同的名称两次),而不是只向我显示错误。

这是我到目前为止的脚本:

#!/bin/sh
if  ! mkdir jpegs 2> /dev/null 
  then
     echo " Cannot create directory \"jpegs\" perhaps it already exists."
     echo "     delete the directory and try again."
     exit
fi
for srcpath in $(find fs282/mirror -iname "*.jpg")
   do
      cp --backup $srcpath  jpegs/ 
   done
echo "List of Duplicate Files Follows"

答案1

不要循环 的输出find。它是不优雅的(在找到所有路径名之前循环不会开始第一次迭代)并且危险(找到的路径名将在空格、制表符和换行符上分割,并且 shell 还将尝试将它们扩展为文件名通配模式)。

相反(如果存在名称冲突,这一切都假设您不想复制找到的文件):

find fs282/mirror -type f -iname '*.jpeg' -exec sh -c '
    for pathname do
        if [ -e "jpegs/${pathname##*/}" ]; then
            printf "%s\n" "${pathname##*/}"
        else
            cp "$pathname" jpegs/
        fi
    done' sh {} + | sort -u

它用作find内联 shell 脚本的路径名生成器。 find会将找到的路径名传递给脚本,并且它将使用 中的每个路径名迭代这些路径名$pathname。该脚本测试路径名的文件名部分是否存在于目录下jpegs,如果存在,则将路径名末尾的文件名打印到标准输出。如果该文件名不存在jpegs,则复制该文件。

参数替换${pathname##*/}会删除从开头$pathname到最后一个/字符。] 的所有内容,仅保留末尾的文件名部分。

最后sort -u将获取内联脚本打印的所有文件名,并对它们进行排序,同时删除重复项。

另一种方法:

find fs282/mirror -type f -iname '*.jpeg' \
    ! -exec sh -c '[ -e "jpegs/${1##*/}" ] && printf "%s\n" "${1##*/}"' sh {} ';' \
    -exec cp {} jpegs ';' | sort -u

这本质上是同一件事,但表述完全不同。

它使用简短的内联 shell 脚本测试文件名是否存在于 下jpegs,如果存在,则打印文件名(并稍后排序)并find继续处理下一个文件。如果不存在,则复制该文件。

有关的:

相关内容