AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 534190
Accepted
Porcupine
Porcupine
Asked: 2019-08-07 08:40:11 +0800 CST2019-08-07 08:40:11 +0800 CST 2019-08-07 08:40:11 +0800 CST

仅查找包含与文件夹同名的文件的文件夹

  • 772

我想找到所有包含同名(和扩展名.md)的降价文件的子文件夹。

例如:我想查找以下子文件夹:

Apple/Banana/Orange      #Apple/Banana/Orange/Orange.md exists
Apple/Banana             #Apple/Banana/Banana.md exists
Apple/Banana/Papaya      #Apple/Banana/Papaya/Papaya.md exists
  • 注意:目录中可以有其他文件或子目录。

有什么建议么?


可以使用以下代码测试问题的解决方案:

#!/usr/bin/env bash
# - goal: "Test"
# - author: Nikhil Agarwal
# - date: Wednesday, August 07, 2019
# - status: P T' (P: Prototyping, T: Tested)
# - usage: ./Test.sh
# - include:
#   1.
# - refer:
#   1. [directory - Find only those folders that contain a File with the same name as the Folder - Unix & Linux Stack Exchange](https://unix.stackexchange.com/questions/534190/find-only-those-folders-that-contain-a-file-with-the-same-name-as-the-folder)
# - formatting:
#   shellcheck disable=
#clear

main() {
    TestData
    ExpectedOutput
    TestFunction "${1:?"Please enter a test number, as the first argument, to be executed!"}"
}

TestFunction() {
    echo "Test Function"
    echo "============="
    "Test${1}"
    echo ""
}

Test1() {
    echo "Description: Thor"
    find . -type f -regextype egrep -regex '.*/([^/]+)/\1\.md$' | sort
    echo "Observation: ${Green:=}Pass, but shows filepath instead of directory path${Normal:=}"
}

Test2() {
    echo "Description: Kusalananda1"
    find . -type d -exec sh -c '
    dirpath=$1
    set -- "$dirpath"/*.md
    [ -f "$dirpath/${dirpath##*/}.md" ] && [ "$#" -eq 1 ]' sh {} \; -print | sort
    echo "Observation: ${Red:=}Fails as it ignores B.md${Normal:=}"
}

Test3() {
    echo "Description: Kusalananda2"
    find . -type d -exec sh -c '
    for dirpath do
        set -- "$dirpath"/*.md
        if [ -f "$dirpath/${dirpath##*/}.md" ] && [ "$#" -eq 1 ]
        then
            printf "%s\n" "$dirpath"
        fi
    done' sh {} + | sort
    echo "Observation: ${Red:=}Fails as it ignores B.md${Normal:=}"
}

Test4() {
    echo "Description: steeldriver1"
    find . -type d -exec sh -c '[ -f "$1/${1##*/}.md" ]' find-sh {} \; -print | sort
    echo "Observation: ${Green:=}Pass${Normal:=}"
}

Test5() {
    echo "Description: steeldriver2"
    find . -type d -exec sh -c '
  for d do
    [ -f "$d/${d##*/}.md" ] && printf "%s\n" "$d"
  done' find-sh {} + | sort
    echo "Observation: ${Green:=}Pass${Normal:=}"
}

Test6() {
    echo "Description: Stéphane Chazelas"
    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}'
    echo "Observation: ${Red:=}Fails as it ignores B.md${Normal:=}"
}

Test7() {
    echo "Description: Zach"
    #shellcheck disable=2044
    for fd in $(find . -type d); do
        dir=${fd##*/}
        if [ -f "${fd}/${dir}.md" ]; then
            ls "${fd}/${dir}.md"
        fi
    done
    echo "Observation: ${Green:=}Pass but shows filepath instead of directory${Normal:=}"
}
ExpectedOutput() {
    echo "Expected Output"
    echo "==============="
    cat << EOT
./GeneratedTest/A
./GeneratedTest/A/AA
./GeneratedTest/B
./GeneratedTest/C/CC1
./GeneratedTest/C/CC2
EOT
}

TestData() {
    rm -rf GeneratedTest

    mkdir -p GeneratedTest/A/AA
    touch GeneratedTest/index.md
    touch GeneratedTest/A/A.md
    touch GeneratedTest/A/AA/AA.md

    mkdir -p GeneratedTest/B
    touch GeneratedTest/B/B.md
    touch GeneratedTest/B/index.md

    mkdir -p GeneratedTest/C/CC1
    touch GeneratedTest/C/index.md
    touch GeneratedTest/C/CC1/CC1.md

    mkdir -p GeneratedTest/C/CC2
    touch GeneratedTest/C/CC2/CC2.md

    mkdir -p GeneratedTest/C/CC3
    touch GeneratedTest/C/CC3/CC.md

    mkdir -p GeneratedTest/C/CC4
}
main "$@"
find directory
  • 6 6 个回答
  • 1141 Views

6 个回答

  • Voted
  1. Best Answer
    Thor
    2019-08-07T09:46:33+08:002019-08-07T09:46:33+08:00

    假设您的文件命名合理,即不需要-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
    
    • 12
  2. Kusalananda
    2019-08-07T08:51:59+08:002019-08-07T08:51:59+08:00
    find . -type d -exec sh -c '
        dirpath=$1
        set -- "$dirpath"/*.md
        [ -f "$dirpath/${dirpath##*/}.md" ] && [ "$#" -eq 1 ]' sh {} \; -print
    

    以上将找到当前目录下的所有目录(包括当前目录),并为每个目录执行一个简短的 shell 脚本。

    shell 代码会测试目录中是否存在与目录同名的 markdown 文件,以及这是否是该*.md目录中唯一的名称。如果存在这样的文件并且它是唯一的*.md名称,则内联 shell 脚本将以零退出状态退出。否则,它会以非零退出状态(信号失败)退出。

    该set -- "$dirpath"/*.md位将位置参数设置为与模式匹配的路径名列表(匹配目录中带有后缀.md的任何名称)。然后我们可以稍后使用$#来查看我们从中获得了多少匹配项。

    如果 shell 脚本成功退出,-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 {} +
    

    也可以看看:

    • 了解 `find` 的 -exec 选项
    • 6
  3. Stéphane Chazelas
    2019-08-07T09:01:45+08:002019-08-07T09:01:45+08:00

    在 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
  4. steeldriver
    2019-08-07T08:51:26+08:002019-08-07T08:51:26+08:00

    任何一个

    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是一个任意字符串,它成为 shell 的第零个位置参数$0- 让它成为令人难忘的东西可能有助于调试,以防 shell 遇到错误(其他人可能建议使用普通sh甚至_作为默认的“跳过”参数)。

    • 4
  5. user208145
    2019-08-08T16:01:50+08:002019-08-08T16:01:50+08:00

    这是我的。我添加了一些更多的目录和文件来验证。我也很无聊,所以我添加了最后修改时间和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
  6. Zach Sanchez
    2019-08-07T08:50:24+08:002019-08-07T08:50:24+08:00

    这需要一点逻辑。

    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

相关问题

  • 如果未引用 -name 后面的模式,则 find 的奇怪行为

  • 将变量从子shell打印到父shell [重复]

  • 检查某个文件夹是否存在于某个目录中

  • 从命令行查找和替换 CSS 文件中的颜色

  • GNU find:在-exec中获取绝对和相对路径

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve