LINUX.ORG.RU

bash find *pattern*

 ,


0

3

Делаю скрипт, который перебирает все файлы с расширением *.ext1 и по каждому найденному file.ext1 должен найти файл с расширением ext2 но с таким же именем file, т.е. зная file.ext1 ищем file.ext2

вот такой код:
find "." -type f -iname «*.ext1» | sort | while read file_ext1
do
myFILE_basename=$(basename «$file_ext1») # убираем путь к файлу
myFILE_name=${myFILE_basename%.*} # убираем расширение, получаем только имя файла

find "." -type f -iname «${myFILE_name}.ext2» | sort | while read file_ext2
do
echo «$file_ext1»
echo «$file_ext2»
done;
done;

Все отлично работает на файлах, содержащих буквы, цифры, пробелы. Но совершенно не работает на файлах, имеющих в названиях '[', ']' или ещё какую экзотику типа спецсимволов.

Т.е. если рядом будут лежать файлы:
file1[my].ext1
file1[my].ext2
-то второй фал не будет найден.

Если строчку
find "." -type f -iname «${myFILE_name}.ext2»
заменить на
find "." -type f -iname «*.ext2» | grep «${myFILE_name}»
- тоже ничего не получиться.

Как засунуть в паттерн имя файла, содержащее спец символы?



Последнее исправление: bre (всего исправлений: 4)

Ответ на: комментарий от alozovskoy

Наверно можно и на питоне, но с ним я не разбирался ещё. А вот на баш-скрипт уже много написал, но реально не могу обойти эту проблему.

bre
() автор топика
find "." -type f -iname "*.ext2" | grep -F "${myFILE_name}.ext2"

Так должно работать. Ключ -F для grep указывает искать в точности указанную строку.

serfeo
()
#!/usr/bin/python3

import os
import fnmatch

def f(a, b, c):
    return [(x[:-5], os.path.join(a, x))
        for x in fnmatch.filter(b, c)]

l1, l2 = [], []
for dname, dnames, fnames in os.walk('.'):
    l1 += f(dname, fnames, '*.ext1')
    l2 += f(dname, fnames, '*.ext2')

l2 = dict(l2)
for a, b in l1:
    if a in l2:
        print(b, l2[a])
anonymous
()

Используй LORCODE, в частности тег [code]. А то текст ни прочитать, ни скопировать.

Твоя проблема в том, что '[', ']' и т. п. символы воспринимаются как спецсимволы регулярки, а не как часть имени файла. Еще проблема, что я не нашел правил регулярок find. Но у менять есть готовый рецепт для sed, а у find есть опция -regextype.

Вот это работает (заменено 2 строки по сравнению с твоим):

#!/bin/bash

find "." -type f -iname "*.ext1" | sort | while read file_ext1;  do
	myFILE_basename=$(basename "$file_ext1")
	myFILE_name=$( echo "${myFILE_basename%.*}" | sed 's/\\/\\\\/g; s/\//\\\//g; s/\./\\./g; s/\*/\\*/g; s/\^/\\^/g; s/\$/\\$/g; s/\[/\\[/g; s/\]/\\]/g;' )
	
	find "." -type f -regextype sed -iname "${myFILE_name}.ext2" | sort | while read file_ext2 ; do
		echo "$file_ext1"
		echo "$file_ext2"
	done
done

Kroz ★★★★★
()
Последнее исправление: Kroz (всего исправлений: 1)
Ответ на: комментарий от Kroz

Ок, если не сложно, что делает SED в таком исполнении? заменяет спец символы на какие-то другие? А -regextype sed меняет их в обратную сторону?

bre
() автор топика
Ответ на: комментарий от bre

что делает SED в таком исполнении?

Экранирует спец. символы:

s/\\/\\\\/g; '\' -> '\\'
s/\//\\\//g; '/' -> '\/'
s/\./\\./g;  '.' -> '\.'
s/\*/\\*/g;  '*' -> '\*'
s/\^/\\^/g;  '^' -> '\^'
s/\$/\\$/g;  '$' -> '\$'
s/\[/\\[/g;  '[' -> '\['
s/\]/\\]/g;  ']' -> '\]'

А -regextype sed меняет их в обратную сторону?

Главная проблема с регулярками в том, что народ не договорился когда и что экранировать. Есть несколько нотаций. Например:

$ echo 'theeeee text ' | grep 'e\{2,5\}'
theeeee text
$ echo 'theeeee text ' | grep -E 'e\{2,5\}'
$ echo 'theeeee text ' | grep -E 'e{2,5}'
theeeee text
То есть в basic regexp (который в grep по умолчанию) фигурные скобки не нужно экранировать (а если экранировать, то они будут трактоваться как спецсимволы), а в Extended regexp - всё с точностью до наоборот.

Как в find по умолчанию я не нашел. C -regextype sed я гарантировал, что find будет вести себя в точности как sed. А для sed я знаю какие символы нужно экранировать: \/.*^$[] . Что и делает | sed '...'.

Kroz ★★★★★
()
Последнее исправление: Kroz (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.