Pertanyaan Mencari nama file duplikat dalam hierarki folder?


Saya memiliki folder bernama img, folder ini memiliki banyak tingkat sub-folder, yang semuanya berisi gambar. Saya akan mengimpornya ke server gambar.

Biasanya gambar (atau file apa pun) dapat memiliki nama yang sama selama berada di jalur direktori yang berbeda atau memiliki ekstensi yang berbeda. Namun, server gambar yang saya impor ke dalamnya mengharuskan semua nama gambar menjadi unik (meskipun ekstensi berbeda).

Misalnya gambar background.png dan background.gif tidak akan diizinkan karena meskipun mereka memiliki ekstensi yang berbeda, mereka masih memiliki nama file yang sama. Bahkan jika mereka berada di sub-folder terpisah, mereka masih harus unik.

Jadi saya bertanya - tanya apakah saya bisa melakukan pencarian rekursif di img folder untuk mencari daftar file yang memiliki nama yang sama (tidak termasuk ekstensi).

Apakah ada perintah yang dapat melakukan ini?


22
2018-06-13 15:28


asal


Ini jauh lebih sulit dari yang saya kira awalnya. Saya ingin satu liner tetapi kebanyakan semuanya memaksa Anda menjadi solusi yang tidak dapat diandalkan untuk membuat panggilan exec. Dicoba selama satu jam. Saya bisa membuatnya bekerja di Linx tetapi bukan AIX saya atau kotak HP. - ojblass
baik-baik saja itu melakukan seperti neraka tetapi berhasil - ojblass
@DavidFoerster Kamu benar! Saya tidak tahu mengapa saya berpikir ini mungkin duplikat Bagaimana menemukan (dan menghapus) file duplikat, tetapi jelas tidak. - Eliah Kagan


Jawaban:


FSlint  Install fslint adalah pencari duplikat serbaguna yang menyertakan fungsi untuk menemukan nama duplikat:

FSlint

Paket FSlint untuk Ubuntu menekankan antarmuka grafis, tetapi seperti yang dijelaskan di FAQ FSlint antarmuka baris perintah tersedia melalui program di /usr/share/fslint/fslint/. Menggunakan --help pilihan untuk dokumentasi, misalnya:

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

Contoh penggunaan:

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

15
2018-06-13 19:02



Terima kasih atas sarannya, apakah Anda tahu jika FSlint dapat digunakan pada baris perintah? - JD Isaacks
@ John Saya telah memperbarui jawaban untuk menjelaskan FSlint's CLI. - ændrük
Terima kasih, ini berhasil. Beberapa hasilnya berwarna ungu dan beberapa berwarna hijau. Apakah Anda tahu dari siapa warna-warna yang berbeda itu? - JD Isaacks
@ John Sepertinya itu menggunakan FSlint ls -l untuk memformat outputnya. Pertanyaan ini harus menjelaskan apa artinya warna. - ændrük
FSlint punya banyak ketergantungan. - Navin


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

Seperti yang dinyatakan oleh komentar, ini juga akan menemukan folder. Berikut adalah perintah untuk membatasinya ke file:

find . -mindepth 1 -type f -printf '%p %f\n' | ...

26
2018-06-13 20:57



Ini adalah cara Linux. Namun ini juga cocok dengan folder - glebm
Jawaban diperbarui untuk mengecualikan direktori. Terima kasih atas komentarmu. - ojblass
Saya mengubah solusinya sehingga mengembalikan path penuh (relatif) dari semua duplikat. Sayangnya ini mengasumsikan bahwa nama path tidak mengandung spasi karena uniq tidak menyediakan fitur untuk memilih pemisah bidang yang berbeda. - David Foerster
@DavidFoerster, rev 6 Anda adalah peningkatan, tetapi mengenai komentar Anda di sana, sejak kapan sed usang? Batin? Yakin. Usang? Bukannya aku sadar. (Dan saya hanya mencari untuk memeriksa.) - cp.engr
@ cp.engr: sed tidak usang. Ajakan itu menjadi usang setelah perubahan saya yang lain. - David Foerster


Simpan ini ke file bernama 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

Kemudian buat file dieksekusi:

chmod +x duplicates.py

Jalankan dalam mis. seperti ini:

./duplicates.py ~/images

Ini harus menghasilkan pasangan file yang memiliki nama dasar yang sama (1). Ditulis dengan python, Anda harus dapat memodifikasinya.


5
2018-06-13 21:01





Saya berasumsi Anda hanya perlu melihat "duplikat" ini, lalu menanganinya secara manual. Jika demikian, kode bash4 ini harus melakukan apa yang Anda inginkan, saya pikir.

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

Lihat http://mywiki.wooledge.org/BashGuide/Arrays#Associative_Arrays dan / atau manual bash untuk bantuan pada sintaksis array asosiatif.


3
2018-06-13 18:23



Bagaimana saya menjalankan perintah seperti itu di terminal? Apakah ini sesuatu yang perlu saya simpan ke file terlebih dahulu dan jalankan file? - JD Isaacks
@ John Isaacks Anda dapat menyalin / menempelkannya ke terminal atau Anda dapat meletakkannya di dalam file dan menjalankannya sebagai skrip. Kedua kasus akan mencapai hal yang sama. - geirha


Ini adalah 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"

Jadikan itu dapat dieksekusi:

chmod a+x bname 

Meminjamnya:

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

Pro:

  • Ini mudah dan sederhana, sehingga dapat diperluas.
  • Menangani kosong, tab, linebreak, dan pagefeeds dalam nama file, afaik. (Dengan asumsi tidak ada yang namanya ekstensi).

Menipu:

  • Ia selalu menemukan file itu sendiri, dan jika menemukan a.gif untuk a.jpg, ia akan mencari a.jpg untuk a.gif juga. Jadi untuk 10 file dengan basename yang sama, ia menemukan 100 pertandingan pada akhirnya.

1
2018-06-13 20:15