У меня следующая проблема:
В каталоге Example1
три файла: Example1
, Things
и Pictures
.
В каталоге Example2
три файла: Example2
, Example3
и Pictures
.
Мне нужен список, показывающий только те файлы, которые соответствуют имени каталога, это: Example1
и Example2
. Я пробовал использовать diff, find, locate и ls..., но ничего не добился.
решение1
Вы можете легко сопоставить имена файлов, которые имеют то же имя, что и содержащий каталог, с регулярным выражением, используя обратную ссылку. Это имена файлов в форме, what/ever/something/something
где две something
части идентичны и не содержат слеша. В синтаксисе регулярных выражений BRE [^/]*
соответствует любой строке, которая не содержит слеша, \(/[^/]*\)
соответствует слешу, за которым следует любое количество символов, не являющихся слешем, и делает все это группой, и \1
соответствует тому же тексту, который соответствует первой группе, поэтому \(/[^/]*\)\1
соответствует двум сегментам пути с одинаковым именем. Добавьте .*
в начало, чтобы соответствовать предыдущим компонентам каталога.
С помощью GNU find, FreeBSD find, macOS find или любой другой, find
которая поддерживает -regex
:
find . -regex '.*\(/[^/]*\)\1'
решение2
Поскольку каталогов, как правило, меньше, чем файлов, давайте найдем все каталоги, а затем проверим, содержат ли они требуемое имя файла.
find . -type d -exec sh -c '
for dirpath do
filepath="$dirpath/${dirpath##*/}"
[ -f "$filepath" ] && printf "%s\n" "$filepath"
done' sh {} +
Это позволит вывести пути ко всем обычным файлам (и символическим ссылкам на обычные файлы), расположенным в каталоге с тем же именем, что и у файла.
Тест выполняется в коротком встроенном sh -c
скрипте, который получает несколько путей к каталогам в качестве аргументов. Он перебирает каждый путь к каталогу и создает путь к файлу с именем, которое мы ищем. ${dirpath##*/}
В коде можно заменить на $(basename "$dirpath")
.
Для данного примера структуры каталогов это выведет
./Example1/Example1
./Example2/Example2
Чтобы просто проверитьлюбое имя, а не просто обычные файлы, измените -f
тест на -e
тест.
решение3
Использовать find -exec
:
find . -type f \
-exec sh -c '[ "$(basename "$1")" = "$(basename "$(dirname "$1")")" ]' find-sh {} \; \
-print
Выполнение -print
будет выполнено только в том случае, если результат внутреннего выражения [ ... ]
будет -exec sh -c '...'
истинным.
Выход:
./Example1/Example1
./Example2/Example2