Найти только те папки, которые содержат файл с тем же именем, что и у папки

Не используйте циклы оболочки для обработки текста.

Здесь awk— правильный инструмент для этой задачи. Но вам нужно вызвать его только один раз:

awk -v OFS='\t' '
  NR == 1 {print $1, "name", "value"; split($0, header); next}
  {for (i = 2; i < NF; i++) print $1, header[i], $i}' < your-file

(вариация на ответ Романа)

8
08.08.2019, 00:26
6 ответов

Предполагая, что ваши файлы имеют разумные имена, т. е. нет необходимости в -print0и т. д. Вы можете сделать это с помощью GNU find следующим образом:

find. -type f -regextype egrep -regex '.*/([^/]+)/\1\.md$'

Выход:

./Apple/Banana/Orange/Orange.md
./Apple/Banana/Papaya/Papaya.md
./Apple/Banana/Banana.md

Если вам нужно только имя каталога, добавьте аргумент -printf:

find. -type f -regextype egrep -regex '.*/([^/]+)/\1\.md$' -printf '%h\n'

Вывод при запуске обновленных тестовых данных:

GeneratedTest/A/AA
GeneratedTest/A
GeneratedTest/C/CC2
GeneratedTest/C/CC1
GeneratedTest/B
13
27.01.2020, 20:08

Это потребует немного логики.

for fd in `find. -type d`; do
  dir=${fd##*/}
  if [ -f ${fd}/${dir}.md ]; then
    ls ${fd}/${dir}.md
  fi
done

Вы также можете адаптировать это, чтобы поместиться в один лайнер, используя кодовые блоки.

РЕДАКТИРОВАТЬ :Bash сложно. basedirне является командой, dirnameне делает то, что я думал, так что давайте перейдем к расширению параметра.

-1
27.01.2020, 20:08

Либо

find. -type d -exec sh -c '[ -f "$1/${1##*/}.md" ]' find-sh {} \; -print

или

find. -type d -exec sh -c '
  for d do
    [ -f "$d/${d##*/}.md" ] && printf "%s\n" "$d"
  done' find-sh {} +

Чтобы избежать запуска одного shдля каждого файла.

find-sh— это произвольная строка, которая становится нулевым позиционным параметром оболочки$0-делает ее чем-то запоминающимся, может помочь при отладке в случае возникновения ошибок оболочки (другие могут предложить использовать обычный shили даже _в качестве параметра пропуска по умолчанию ).

4
27.01.2020, 20:08

В системе GNU вы можете сделать что-то вроде:

find. -name '*.md' -print0 |
  gawk -v RS='\0' -F/ -v OFS=/ '
    {filename = $NF; NF--
     if ($(NF)".md" == filename) include[$0]
     else exclude[$0]
    }
    END {for (i in include) if (!(i in exclude)) print i}'
6
27.01.2020, 20:08
find. -type d -exec sh -c '
    dirpath=$1
    set -- "$dirpath"/*.md
    [ -f "$dirpath/${dirpath##*/}.md" ] && [ "$#" -eq 1 ]' sh {} \; -print

Приведенный выше код найдет все каталоги ниже текущего каталога (, включая текущий каталог ), и для каждого из них будет выполнен короткий сценарий оболочки.

Шелл-код будет проверять, существует ли уцененный файл с тем же именем, что и у каталога внутри каталога, и является ли это единственным *.mdименем в этом каталоге. Если такой файл существует и если это единственное имя *.md, встроенный сценарий оболочки завершается с нулевым статусом выхода. В противном случае он завершается с не--нулевым статусом выхода (, сигнализируя о сбое ).

Бит set -- "$dirpath"/*.mdустановит позиционные параметры в список имен путей, соответствующих шаблону (соответствует любому имени с суффиксом .mdв каталоге ). Затем мы можем использовать $#позже, чтобы увидеть, сколько совпадений мы получили от этого.

Если сценарий оболочки завершится успешно, -printнапечатает путь к найденному каталогу.

Немного более быстрая версия, использующая меньше вызовов встроенного скрипта,но это не позволяет вам делать больше с найденными путями в самом find(хотя встроенный скрипт может быть дополнительно расширен):

find. -type d -exec sh -c '
    for dirpath do
        set -- "$dirpath"/*.md
        [ -f "$dirpath/${dirpath##*/}.md" ] &&
        [ "$#" -eq 1 ] &&
        printf "%s\n" "$dirpath"
    done' sh {} +

Те же команды, но не заботясь о том, есть ли другие .mdфайлы в каталогах:

find. -type d -exec sh -c '
    dirpath=$1
    [ -f "$dirpath/${dirpath##*/}.md" ]' sh {} \; -print
find. -type d -exec sh -c '
    for dirpath do
        [ -f "$dirpath/${dirpath##*/}.md" ] &&
        printf "%s\n" "$dirpath"
    done' sh {} +

См. также:

6
27.01.2020, 20:08

Вот мой. Я добавил еще несколько каталогов и файлов для проверки. Мне тоже было скучно, поэтому я добавил время последней модификации и MD5. Возможно, вы ищете дубликаты.

GREEN='\033[0;32m'
RED='\033[0;31m'
NC='\033[0m'

mkdir -pv {Pear,Grape,Raisin,Plaintain}/{DragonFruit,Nababa,Strawberry,Grape,Raisin}
touch {Pear,Grape,Raisin,Plaintain}/{DragonFruit,Nababa,Strawberry,Grape,Raisin}/{Strawberry,Grape,Raisin}.md

for dir in $(find./ -type d)
do
    dirname="${dir##*/}"
    fname="${dirname}.md"
    if [ -f "${dir}/${fname}" ]
    then
        STAT=$(stat --printf="%y %s" "${dir}/${fname}")
        STAT="${STAT:0:19}"
        MD5=$(md5sum "${dir}/${fname}")
        MD5="${MD5:0:32}"
        printf "${GREEN}%-60s${NC}%-40s%-40s\n" "'${dir}/${fname}' exists" "$STAT" "$MD5"
    else
        echo -e "${RED}'${dir}/${fname}' doesn't exist${NC}"
    fi
done

'.//.md' doesn't exist
'./Raisin/Raisin.md' doesn't exist
'./Raisin/Raisin/Raisin.md' exists                          2019-08-07 19:54:09      a3085274bf23c52c58dd063faba0c36a
'./Raisin/Nababa/Nababa.md' doesn't exist
'./Raisin/Strawberry/Strawberry.md' exists                  2019-08-07 19:54:09      3d2eca1d4a3c539527cb956affa8b807
'./Raisin/Grape/Grape.md' exists                            2019-08-07 19:54:09      f577b20f93a51286423c1d8973973f01
'./Raisin/DragonFruit/DragonFruit.md' doesn't exist
'./Pear/Pear.md' doesn't exist
'./Pear/Raisin/Raisin.md' exists                            2019-08-07 19:54:09      61387f5d87f125923c2962b389b0dd67
'./Pear/Nababa/Nababa.md' doesn't exist
'./Pear/Strawberry/Strawberry.md' exists                    2019-08-07 19:54:09      02c9e39ba5b77954082a61236f786d34
'./Pear/Grape/Grape.md' exists                              2019-08-07 19:54:09      43e85d5651cac069bba8ba36e754079d
'./Pear/DragonFruit/DragonFruit.md' doesn't exist
'./Apple/Apple.md' doesn't exist
'./Apple/Banana/Banana.md' exists                           2019-08-07 19:54:09      a605268f3314411ec360d7e0dd234960
'./Apple/Banana/Papaya/Papaya.md' exists                    2019-08-07 19:54:09      e759a879942fe986397e52b7ba21a9ff
'./Apple/Banana/Orange/Orange.md' exists                    2019-08-07 19:54:09      127618fe9ab73937836b809fa0593572
'./Plaintain/Plaintain.md' doesn't exist
'./Plaintain/Raisin/Raisin.md' exists                       2019-08-07 19:54:09      13ed6460f658ca9f7d222ad3d07212a2
'./Plaintain/Nababa/Nababa.md' doesn't exist
'./Plaintain/Strawberry/Strawberry.md' exists               2019-08-07 19:54:09      721d7a5a32f3eacf4b199b74d78b91f0
'./Plaintain/Grape/Grape.md' exists                         2019-08-07 19:54:09      0bdaff592bbd9e2ed5fac5a992bb3566
'./Plaintain/DragonFruit/DragonFruit.md' doesn't exist
'./Grape/Grape.md' doesn't exist
'./Grape/Raisin/Raisin.md' exists                           2019-08-07 19:54:09      aa5d4c970e7b4b6dc35cd16d1863b5bb
'./Grape/Nababa/Nababa.md' doesn't exist
'./Grape/Strawberry/Strawberry.md' exists                   2019-08-07 19:54:09      8b02f8273bbff1bb3162cb088813e0c9
'./Grape/Grape/Grape.md' exists                             2019-08-07 19:54:09      5593d7d6fdcbb48ab5901ba30469bbe8
0
27.01.2020, 20:08

Теги

Похожие вопросы