동일한 이름(및 확장자)을 가진 마크다운 파일이 포함된 모든 .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 "$@"
답변1
파일 이름이 적절하게 지정되었다고 가정하면, 즉 -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
답변2
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}'
답변3
find . -type d -exec sh -c '
dirpath=$1
set -- "$dirpath"/*.md
[ -f "$dirpath/${dirpath##*/}.md" ] && [ "$#" -eq 1 ]' sh {} \; -print
위의 코드는 현재 디렉토리 아래(포함)의 모든 디렉토리를 찾고 각 디렉토리에 대해 짧은 쉘 스크립트를 실행합니다.
쉘 코드는 디렉토리와 동일한 이름을 가진 마크다운 파일이 디렉토리에 존재하는지, 그리고 이것이 *.md
디렉토리에 유일한 이름인지 테스트합니다. 그러한 파일이 존재하고 고유한 이름인 경우 *.md
인라인 쉘 스크립트는 0 종료 상태로 종료됩니다. 그렇지 않으면 0이 아닌 종료 상태(신호 실패)로 종료됩니다.
이 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 {} +
또한보십시오:
답변4
이 내 꺼야. 확인하기 위해 더 많은 디렉터리와 파일을 추가했습니다. 저도 심심해서 마지막 수정시간과 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