フォルダー階層内で重複するファイル名を検索しますか?


29

というフォルダがありimg、このフォルダには多くのレベルのサブフォルダがあり、すべてに画像が含まれています。それらを画像サーバーにインポートします。

通常、イメージ(または任意のファイル)は、異なるディレクトリパスにあるか、拡張子が異なる限り、同じ名前を持つことができます。ただし、インポートするイメージサーバーでは、すべてのイメージ名が一意である必要があります(拡張子が異なっていても)。

たとえば、画像background.pngbackground.gifは、拡張子が異なっていても同じファイル名であるため許可されません。それらが別々のサブフォルダーにある場合でも、それらはまだ一意である必要があります。

そのimgため、同じ名前(拡張子を除く)を持つファイルのリストを見つけるために、フォルダー内で再帰検索を実行できるかどうか疑問に思っています。

これを実行できるコマンドはありますか?


@DavidFoersterその通りです!なぜ重複ファイルを検索(および削除)する方法の複製であると考えたのかはわかりませんが、明らかにそうではありません。
エリアケイガン

回答:


17

FSlint fslintをインストールするは、重複する名前を見つけるための機能を備えた多用途の重複ファインダーです。

FSlint

UbuntuのFSlintパッケージはグラフィカルインターフェイスを強調していますが、FSlint FAQで説明されているように、コマンドラインインターフェイスはのプログラムを介して利用できます/usr/share/fslint/fslint/--help文書化のオプションを使用します。例:

$ /usr/share/fslint/fslint/fslint --help
File system lint.
A collection of utilities to find lint on a filesystem.
To get more info on each utility run 'util --help'.

findup -- find DUPlicate files
findnl -- find Name Lint (problems with filenames)
findu8 -- find filenames with invalid utf8 encoding
findbl -- find Bad Links (various problems with symlinks)
findsn -- find Same Name (problems with clashing names)
finded -- find Empty Directories
findid -- find files with dead user IDs
findns -- find Non Stripped executables
findrs -- find Redundant Whitespace in files
findtf -- find Temporary Files
findul -- find possibly Unused Libraries
zipdir -- Reclaim wasted space in ext2 directory entries
$ /usr/share/fslint/fslint/findsn --help
find (files) with duplicate or conflicting names.
Usage: findsn [-A -c -C] [[-r] [-f] paths(s) ...]

If no arguments are supplied the $PATH is searched for any redundant
or conflicting files.

-A reports all aliases (soft and hard links) to files.
If no path(s) specified then the $PATH is searched.

If only path(s) specified then they are checked for duplicate named
files. You can qualify this with -C to ignore case in this search.
Qualifying with -c is more restictive as only files (or directories)
in the same directory whose names differ only in case are reported.
I.E. -c will flag files & directories that will conflict if transfered
to a case insensitive file system. Note if -c or -C specified and
no path(s) specifed the current directory is assumed.

使用例:

$ /usr/share/fslint/fslint/findsn /usr/share/icons/ > icons-with-duplicate-names.txt
$ head icons-with-duplicate-names.txt 
-rw-r--r-- 1 root root    683 2011-04-15 10:31 Humanity-Dark/AUTHORS
-rw-r--r-- 1 root root    683 2011-04-15 10:31 Humanity/AUTHORS
-rw-r--r-- 1 root root  17992 2011-04-15 10:31 Humanity-Dark/COPYING
-rw-r--r-- 1 root root  17992 2011-04-15 10:31 Humanity/COPYING
-rw-r--r-- 1 root root   4776 2011-03-29 08:57 Faenza/apps/16/DC++.xpm
-rw-r--r-- 1 root root   3816 2011-03-29 08:57 Faenza/apps/22/DC++.xpm
-rw-r--r-- 1 root root   4008 2011-03-29 08:57 Faenza/apps/24/DC++.xpm
-rw-r--r-- 1 root root   4456 2011-03-29 08:57 Faenza/apps/32/DC++.xpm
-rw-r--r-- 1 root root   7336 2011-03-29 08:57 Faenza/apps/48/DC++.xpm
-rw-r--r-- 1 root root    918 2011-03-29 09:03 Faenza/apps/16/Thunar.png

これが働いてくれてありがとう。結果の一部は紫色で、一部は緑色です。さまざまな色が何を意味するのか知っていますか?
JDイザックス

@John FSlintがls -l出力のフォーマットに使用しているようです。この質問では、色の意味を説明する必要があります。
アーンドリューク

FSlintには多くの依存関係があります。
ナビン

31
find . -mindepth 1 -printf '%h %f\n' | sort -t ' ' -k 2,2 | uniq -f 1 --all-repeated=separate | tr ' ' '/'

コメントが述べているように、これはフォルダも見つけます。ファイルに制限するコマンドは次のとおりです。

find . -mindepth 1 -type f -printf '%p %f\n' | sort -t ' ' -k 2,2 | uniq -f 1 --all-repeated=separate | cut -d' ' -f1

すべての重複の完全な(相対)パスを返すようにソリューションを変更しました。残念ながらuniq、異なるフィールド区切り文字を選択する機能が提供されていないため、パス名に空白が含まれていないと想定しています。
デビッドフォースター

@DavidFoerster、あなたのrev 6は改善されましたが、あなたのコメントに関しては、いつsed廃止されるのですか?不可解?確かに。時代遅れ?私が知っていることではありません。(そして確認するために検索しました。)
cp.engr

@ cp.engr:sedは廃止されていません。呼び出しは、私の別の変更後に廃止されました。
デビッドフォースター

@DavidFoerster、時代遅れは私にとって正しい言葉のようには思えません。「不要」がより適切だと思います。とにかく、明確にしてくれてありがとう。
cp.engr

@ cp.engr:提案をありがとう!私はその言葉を知りませんでしたが、状況によく合っているようです。
デビッドフォースター

8

これを次の名前のファイルに保存します duplicates.py

#!/usr/bin/env python

# Syntax: duplicates.py DIRECTORY

import os, sys

top = sys.argv[1]
d = {}

for root, dirs, files in os.walk(top, topdown=False):
    for name in files:
        fn = os.path.join(root, name)
        basename, extension = os.path.splitext(name)

        basename = basename.lower() # ignore case

        if basename in d:
            print(d[basename])
            print(fn)
        else:
            d[basename] = fn

次に、ファイルを実行可能にします。

chmod +x duplicates.py

次のように実行します。

./duplicates.py ~/images

同じbasename(1)を持つファイルのペアを出力する必要があります。Pythonで書かれており、修正できるはずです。


適切に動作していないようです。それは重複として検出しP001.ORF、またP001 (1).ORF私のファイルの60%が重複していると考えているようです。これは間違いです。fslint3%に近い現実的な数の重複ファイル名が見つかりました。
ロルフ

3

これらの「重複」を確認し、それらを手動で処理するだけでよいと想定しています。もしそうなら、このbash4コードはあなたが望むことをするはずです。

declare -A array=() dupes=()
while IFS= read -r -d '' file; do 
    base=${file##*/} base=${base%.*}
    if [[ ${array[$base]} ]]; then 
        dupes[$base]+=" $file"
    else
        array[$base]=$file
    fi
done < <(find /the/dir -type f -print0)

for key in "${!dupes[@]}"; do 
    echo "$key: ${array[$key]}${dupes[$key]}"
done

連想配列構文のヘルプについては、http://mywiki.wooledge.org/BashGuide/Arrays#Associative_Arraysおよび/またはbashマニュアルを参照してください


ターミナルでそのようなコマンドを実行するにはどうすればよいですか?これは最初にファイルに保存してファイルを実行する必要がありますか?
JD Isaacks

@John Isaacksターミナルにコピー/貼り付けするか、ファイルに入れてスクリプトとして実行できます。どちらの場合でも同じことが実現します。
ガイラ

1

これはbnameです。

#!/bin/bash
#
#  find for jpg/png/gif more files of same basename 
#
# echo "processing ($1) $2"
bname=$(basename "$1" .$2)
find -name "$bname.jpg" -or -name "$bname.png"

実行可能にする:

chmod a+x bname 

呼び出す:

for ext in jpg png jpeg gif tiff; do find -name "*.$ext" -exec ./bname "{}" $ext ";"  ; done

プロ:

  • それは簡単でシンプルなため、拡張可能です。
  • ファイル名の空白、タブ、改行、ページフィードを処理します。(拡張名にそのようなものがないと仮定)。

短所:

  • ファイル自体は常に検出され、a.jpgのa.gifが検出されると、a.gifのa.jpgも検出されます。したがって、同じベース名の10個のファイルの場合、最後に100個の一致が見つかります。

0

私のニーズに合わせたloevborgのスクリプトの改善(グループ化された出力、ブラックリスト、スキャン中のクリーナー出力を含む)。10TBドライブをスキャンしていたので、少しきれいな出力が必要でした。

使用法:

python duplicates.py DIRNAME

duplicates.py

    #!/usr/bin/env python

    # Syntax: duplicates.py DIRECTORY

    import os
    import sys

    top = sys.argv[1]
    d = {}

    file_count = 0

    BLACKLIST = [".DS_Store", ]

    for root, dirs, files in os.walk(top, topdown=False):
        for name in files:
            file_count += 1
            fn = os.path.join(root, name)
            basename, extension = os.path.splitext(name)

            # Enable this if you want to ignore case.
            # basename = basename.lower()

            if basename not in BLACKLIST:
                sys.stdout.write(
                    "Scanning... %s files scanned.  Currently looking at ...%s/\r" %
                    (file_count, root[-50:])
                )

                if basename in d:
                    d[basename].append(fn)
                else:
                    d[basename] = [fn, ]

    print("\nDone scanning. Here are the duplicates found: ")

    for k, v in d.items():
        if len(v) > 1:
            print("%s (%s):" % (k, len(v)))
            for f in v:
                print (f)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.