我想找到所有包含同名(和扩展名.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 执行此操作,如下所示:输出:
如果您只想要目录名称,请添加一个
-printf
参数:在更新的测试数据上运行时的输出:
以上将找到当前目录下的所有目录(包括当前目录),并为每个目录执行一个简短的 shell 脚本。
shell 代码会测试目录中是否存在与目录同名的 markdown 文件,以及这是否是该
*.md
目录中唯一的名称。如果存在这样的文件并且它是唯一的*.md
名称,则内联 shell 脚本将以零退出状态退出。否则,它会以非零退出状态(信号失败)退出。该
set -- "$dirpath"/*.md
位将位置参数设置为与模式匹配的路径名列表(匹配目录中带有后缀.md
的任何名称)。然后我们可以稍后使用$#
来查看我们从中获得了多少匹配项。如果 shell 脚本成功退出,
-print
将打印找到的目录的路径。使用较少调用内联脚本的稍微更快的版本,但这并不能让您对找到的路径名
find
本身做更多的事情(内联脚本可能会进一步扩展):相同的命令,但不关心
.md
目录中是否有其他文件:也可以看看:
在 GNU 系统上,您可以执行以下操作:
任何一个
或者
避免
sh
每个文件运行一个。这
find-sh
是一个任意字符串,它成为 shell 的第零个位置参数$0
- 让它成为令人难忘的东西可能有助于调试,以防 shell 遇到错误(其他人可能建议使用普通sh
甚至_
作为默认的“跳过”参数)。这是我的。我添加了一些更多的目录和文件来验证。我也很无聊,所以我添加了最后修改时间和MD5。也许您正在寻找重复项。
这需要一点逻辑。
您还可以通过使用代码块将其调整为适合单行。
编辑:Bash 很难。
basedir
不是命令,dirname
没有做我认为的那样,所以让我们进行参数扩展。