폴더 계층 내에서 중복 파일 이름을 검색 하시겠습니까? (또는 파일)는 다른 디렉토리

나는라는 폴더가 img모두 이미지를 포함,이 폴더 하위 폴더의 많은 수준을 보유하고 있습니다. 이미지 서버로 가져옵니다.

일반적으로 이미지 (또는 파일)는 다른 디렉토리 경로에 있거나 확장자가 다른 한 이름이 동일 할 수 있습니다. 그러나 이미지를 가져 오는 이미지 서버는 모든 이미지 이름이 고유해야합니다 (확장명이 다르더라도).

예를 들어 이미지 background.png와는 background.gif서로 다른 확장에도 불구하고 그들은 여전히 같은 파일 이름을 가지고 있기 때문에 허용되지 않습니다. 별도의 하위 폴더에 있더라도 여전히 고유해야합니다.

따라서 img폴더 에서 재귀 검색을 수행 하여 동일한 이름 (확장자 제외)의 파일 목록을 찾을 수 있는지 궁금합니다 .

이를 수행 할 수있는 명령이 있습니까?



답변

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


답변

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


답변

이것을 파일 이름으로 저장하십시오 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)을 가진 파일 쌍을 출력해야합니다. 파이썬으로 작성하면 수정할 수 있어야합니다.


답변

이 “중복”만보고 수동으로 처리해야한다고 가정합니다. 그렇다면이 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 매뉴얼을 참조 하십시오 .


답변

이것은 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

찬성:

  • 간단하고 간단하므로 확장 가능합니다.
  • 파일 이름에서 공백, 탭, 줄 바꿈 및 페이지 피드를 처리합니다. (extension-name에 그런 것이 없다고 가정).

범죄자:

  • 항상 파일 자체를 찾고 a.jpg의 경우 a.gif를 찾으면 a.gif의 경우 a.jpg도 찾습니다. 따라서 동일한 기본 이름을 가진 10 개의 파일에 대해 결국 100 개의 일치 항목을 찾습니다.

답변

내 필요에 따라 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)


답변