web-dev-qa-db-fra.com

Rechercher les noms de fichiers en double dans la hiérarchie des dossiers?

J'ai un dossier appelé img, ce dossier contient plusieurs niveaux de sous-dossiers, contenant tous des images. Je vais les importer dans un serveur d'images.

Normalement, les images (ou tous les fichiers) peuvent avoir le même nom si elles se trouvent dans un chemin de répertoire différent ou ont une extension différente. Cependant, le serveur d'images dans lequel je les importe nécessite que tous les noms d'image soient uniques (même si les extensions sont différentes).

Par exemple, les images background.png et background.gif ne seraient pas autorisées car, même si elles ont des extensions différentes, elles portent toujours le même nom de fichier. Même s'ils se trouvent dans des sous-dossiers distincts, ils doivent toujours être uniques.

Je me demande donc si je peux effectuer une recherche récursive dans le dossier img pour trouver une liste de fichiers portant le même nom (sans l'extension).

Est-ce qu'il y a une commande qui peut faire ça?

27
JD Isaacks

FSlintInstall fslint est un Finder de doublons polyvalent qui comprend une fonction permettant de rechercher les noms en double:

FSlint

Le paquetage FSlint pour Ubuntu met l’accent sur l’interface graphique, mais comme l’explique la FAQ de FSlint , une interface de ligne de commande est disponible via les programmes de /usr/share/fslint/fslint/. Utilisez l'option --help pour la documentation, par exemple:

$ /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.

Exemple d'utilisation:

$ /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
17
ændrük
find . -mindepth 1 -printf '%h %f\n' | sort -t ' ' -k 2,2 | uniq -f 1 --all-repeated=separate | tr ' ' '/'

Comme le dit le commentaire, cela trouvera également des dossiers. Voici la commande pour le limiter aux fichiers:

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

Enregistrez ceci dans un fichier nommé 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

Ensuite, rendez le fichier exécutable:

chmod +x duplicates.py

Exécuter par exemple comme ça:

./duplicates.py ~/images

Il devrait produire des paires de fichiers qui ont le même nom de base (1). Ecrit en python, vous devriez pouvoir le modifier.

7
loevborg

Je suppose que vous n'avez besoin que de voir ces "doublons", puis de les manipuler manuellement. Si oui, ce code bash4 devrait faire ce que vous voulez, je pense.

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

Voir http://mywiki.wooledge.org/BashGuide/Arrays#Associative_Arrays et/ou le manuel bash pour obtenir de l'aide sur la syntaxe du tableau associatif.

3
geirha

C'est 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"

Rendez-le exécutable:

chmod a+x bname 

Invoquez-le:

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

Pro:

  • C'est simple et simple, donc extensible.
  • Gère les blancs, les tabulations, les sauts de ligne et les sauts de page dans les noms de fichiers, autant que je sache. (En supposant que rien de tel dans l'extension-nom).

Con:

  • Il trouve toujours le fichier lui-même, et s'il trouve a.gif pour a.jpg, il trouvera aussi a.jpg pour a.gif. Donc, pour 10 fichiers du même nom de base, il trouve 100 correspondances à la fin.
1
user unknown

Amélioration du script de loevborg, pour mes besoins (inclut une sortie groupée, une liste noire, une sortie plus nette lors de l'analyse). Je numérisais un disque de 10 To, il me fallait donc une sortie un peu plus propre.

Usage:

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)
0
skoczen