У меня есть папка с именем img, эта папка имеет много уровней подпапок, все из которых содержат изображения. Я буду импортировать их в сервер изображений.
Обычно изображения (или любые файлы) могут иметь одно и то же имя, если они находятся в другом пути к каталогу или имеют другое расширение. Однако импортируемый ими сервер изображений требует, чтобы все имена изображений были уникальными (даже если расширения отличаются друг от друга).
Например, изображения background.png и background.gif не будут разрешены, потому что, хотя у них разные расширения, они все равно имеют одинаковое имя файла.
Так что мне интересно, могу ли я сделать рекурсивный поиск в папке img, чтобы найти список файлов, которые имеют одно и то же имя (исключая расширение).
Есть ли команда, которая может это сделать?
Я предполагаю, что вам нужно только увидеть эти «дубликаты», а затем обработать их вручную. Если это так, этот код bash4 должен делать то, что вы хотите, я думаю.
declare -A array = () dupes = (), в то время как IFS = read -r -d '' file; do base = $ {file ## * /} base = $ {base%. *}, если [[$ {array [$ base]}]]; затем dupes [$ base] + = "$ file" else array [$ base] = $ file fi done & lt; & lt; (find / the / dir -type f -print0) для ключа в "$ {! dupes [@]}"; do echo "$ key: $ {array [$ key]} $ {dupes [$ key]}" done
См. http://mywiki.wooledge.org/BashGuide / Arrays # Associative_Arrays и / или справочник bash для справки по синтаксису ассоциативного массива.
Сохраните это в файле с именем duplicates.py
#! / usr / bin / env python # Синтаксис: duplicates.py Импорт каталога os, sys top = sys.argv [1] d = {} для root, dirs, файлов в os.walk (top, topdown = False): для имени в файлах: fn = os.path.join (root, name) basename, extension = os.path.splitext (name) basename = basename.lower () # игнорировать регистр, если basename в d: print (d [basename]) print (fn) else: d [basename] = fn
Затем сделайте исполняемый файл:
chmod + x duplicates.py
Запустите, например, например:
./ duplicates.py ~ / images
Он должен выводить пары файлов, имеющих одинаковое базовое имя (1). Написанный на python, вы сможете изменить его.
Я предполагаю, что вам нужно только увидеть эти «дубликаты», а затем обработать их вручную. Если это так, этот код bash4 должен делать то, что вы хотите, я думаю.
declare -A array = () dupes = (), в то время как IFS = read -r -d '' file; do base = $ {file ## * /} base = $ {base%. *}, если [[$ {array [$ base]}]]; затем dupes [$ base] + = "$ file" else array [$ base] = $ file fi done & lt; & lt; (find / the / dir -type f -print0) для ключа в "$ {! 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 больше файлов одного и того же basename # # echo "processing ($ 1) $ 2" bname = $ (basename "$ 1". $ 2) find -name "$ bname.jpg" -or -name "$ bname.png"
Сделать его исполняемым:
chmod a + x bname
Вызвать это:
для ext в jpg png jpeg gif tiff; do find -name "*. $ ext" -exec ./bname "{}" $ ext ";" ;
Pro:
Con:
find. -mindepth 1 -printf '% h% f \n' | sort -t '' -k 2,2 | uniq -f 1 - all-repeat = отдельный | tr '' '/'
Как говорится в комментарии, это также найдет папки. Вот команда ограничить его файлами:
find. -mindepth 1-type f -printf '% p% f \n' | ...
uniq
не предоставляет функции для выбора другого разделителя полей.
– David Foerster
16 August 2017 в 22:39
sed
устарел? Arcane? Конечно. Вышло из употребления? Не то чтобы я знал. (И я только что проверил.)
– cp.engr
13 October 2017 в 17:43
Улучшение сценария loevborg для моих нужд (включает в себя сгруппированный вывод, черный список, более чистый вывод во время сканирования).
Использование:
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)
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)
]