Не используйте циклы оболочки для обработки текста.
Здесь 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
(вариация на ответ Романа)
Предполагая, что ваши файлы имеют разумные имена, т. е. нет необходимости в -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
Это потребует немного логики.
for fd in `find. -type d`; do
dir=${fd##*/}
if [ -f ${fd}/${dir}.md ]; then
ls ${fd}/${dir}.md
fi
done
Вы также можете адаптировать это, чтобы поместиться в один лайнер, используя кодовые блоки.
РЕДАКТИРОВАТЬ :Bash сложно. basedir
не является командой, dirname
не делает то, что я думал, так что давайте перейдем к расширению параметра.
Либо
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
или даже _
в качестве параметра пропуска по умолчанию ).
В системе 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}'
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 {} +
См. также:
Вот мой. Я добавил еще несколько каталогов и файлов для проверки. Мне тоже было скучно, поэтому я добавил время последней модификации и 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