Find

僅查找包含與文件夾同名的文件的文件夾

  • August 8, 2019

我想找到所有包含同名(和副檔名.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 "$@"

假設您的文件命名合理,即不需要-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

引用自:https://unix.stackexchange.com/questions/534190