У меня есть папка с именем img, эта папка имеет много уровней подпапок, все из которых содержат изображения. Я буду импортировать их в сервер изображений.
Обычно изображения (или любые файлы) могут иметь одно и то же имя, если они находятся в другом пути к каталогу или имеют другое расширение. Однако импортируемый ими сервер изображений требует, чтобы все имена изображений были уникальными (даже если расширения отличаются друг от друга).
Например, изображения background.png и background.gif не будут разрешены, потому что, хотя у них разные расширения, они все равно имеют одинаковое имя файла.
Так что мне интересно, могу ли я сделать рекурсивный поиск в папке img, чтобы найти список файлов, которые имеют одно и то же имя (исключая расширение).
Есть ли команда, которая может это сделать?
Сохраните это в файле с именем 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, вы сможете изменить его.
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' | ...
Я предполагаю, что вам нужно только увидеть эти «дубликаты», а затем обработать их вручную. Если это так, этот код 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
Pro:
Это простой и простой, поэтому расширяемый. Обрабатывает пробелы, вкладки, строки и файлы в именах файлов, afaik. (Предполагая, что в имени расширения нет такой вещи).Con:
Это просто и просто, поэтому расширяемость.Сохраните это в файле с именем 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, вы сможете изменить его.
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' | ...
Я предполагаю, что вам нужно только увидеть эти «дубликаты», а затем обработать их вручную. Если это так, этот код 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
Pro:
Это простой и простой, поэтому расширяемый. Обрабатывает пробелы, вкладки, строки и файлы в именах файлов, afaik. (Предполагая, что в имени расширения нет такой вещи).Con:
Это просто и просто, поэтому расширяемость.Сохраните это в файле с именем 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, вы сможете изменить его.
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' | ...
Я предполагаю, что вам нужно только увидеть эти «дубликаты», а затем обработать их вручную. Если это так, этот код 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 для получения справки по синтаксис ассоциативного массива.
это имя:
#!/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
плюсы:
это простой и простой, поэтому расширяемым. Обрабатывает пробелы, табы, переносы строк и pagefeeds в именах файлов, насколько мне известно. (Предполагая, что нет такого понятия в имени расширения).минусы:
это просто и понятно, поэтому расширяемым. Сохраните это в файле с именем 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, вы сможете изменить его.
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' | ...
Я предполагаю, что вам нужно только увидеть эти «дубликаты», а затем обработать их вручную. Если это так, этот код 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:
Это 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
Я предполагаю, что вам нужно только увидеть эти «дубликаты», а затем обработать их вручную. Если это так, этот код 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, вы сможете изменить его.
Улучшение сценария 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)
]