エラーの代わりに重複したファイル名を表示するには、Linuxコンソールでスクリプトをインポートしてください。

エラーの代わりに重複したファイル名を表示するには、Linuxコンソールでスクリプトをインポートしてください。

Linux環境で実行するスクリプトを作成しようとしています。

.jpegディレクトリツリーでファイルを見つけ、名前付きディレクトリにコピーしますjpegs

重複したファイル名を表示したいのですが、エラーのみを表示するのではなく、生成されたリストに重複したファイル名を1回だけリストして同じ名前を2回表示しません。

これはこれまで私のスクリプトです。

#!/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。これはエレガントではなく(ループはすべてのパス名が見つかるまで最初の繰り返しを開始しません)、危険です(見つかったパス名はスペース、タブ、および改行に分割され、シェルはファイル名のワイルドカードパターンに拡張しようとします。 )。

代わりに(名前の競合がある場合は、見つかったファイルをコピーしたくないとします):

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インラインシェルスクリプトのパス名ジェネレータとして使用されます。find見つかったパス名はスクリプトに渡され、.NETの各パス名を使用してそのパス名を繰り返します$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

本質的に同じ内容ですが、まったく異なって表現されます。

短いインラインシェルスクリプトを使用してファイル名が下にあるかどうかをテストしjpegs、その場合はファイル名を印刷して後でソートしてから、find次のファイルに進みます。存在しない場合はファイルがコピーされます。

関連:

おすすめ記事