Мне назвали папку img
, эта папка имеет много уровней подпапок, весь из который содержащий изображения. Я собираюсь импортировать их в сервер изображения.
Обычно изображения (или любые файлы) могут иметь то же имя, пока они находятся в другом пути к каталогу или имеют другое расширение. Однако сервер изображения, в который я импортирую их, требует, чтобы все названия картинки были уникальны (даже если расширения отличаются).
Например, изображения background.png
и background.gif
не был бы позволен потому что даже при том, что у них есть различные расширения, у них все еще есть то же имя файла. Даже если они находятся в отдельных подпапках, они все еще должны быть уникальными.
Таким образом, я задаюсь вопросом, могу ли я выполнить в рекурсивном поиске img
папка для нахождения списка файлов, которые имеют то же имя (исключая расширение).
Существует ли команда, которая может сделать это?
FSlint универсальное дублирующееся средство поиска, которое включает функцию для нахождения двойных названий:
Пакет FSlint для Ubuntu подчеркивает графический интерфейс, но как объяснен в FAQ FSlint, интерфейс командной строки доступен с помощью программ в /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
Это должно произвести пар файлов, которые имеют то же базовое имя (1). Записанный в Python, необходимо смочь изменить его.
Я предполагаю, что только необходимо видеть эти "дубликаты", затем обработать их вручную. Если так, этот код 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 и/или руководство удара для справки на синтаксисе ассоциативного массива.
Это - 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
Pro:
Довод "против":
Улучшение сценария loevborg, для моих потребностей (включает сгруппированный вывод, черный список, более чистый вывод при сканировании). Я сканировал диск на 10 ТБ, таким образом, мне был нужен немного более чистый вывод.
Использование:
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)