1
$ ls *
2000-01-01-abcd.md
2000-01-01-cdef.md

I can extract abcd and cdef from the following command

 find *.md -exec sh -c "echo {} | sed 's/.md//' | sed 's/2000-01-01-//'" \;

I know how to add a string in the beginning of the file via sed '1s/^/string/' , but how do I pass the exact string?

How do I pass this string "abcd" and "cdef" in the corresponding files, because I want to add the corresponding strings in each and every file in the beginning of the file.

xhienne
  • 17,075
  • 2
  • 52
  • 68
infoclogged
  • 919
  • 2
  • 11
  • 24

3 Answers3

1

to add the corresponding strings in each and every file in the beginning of the file

bash + sed approach:

for f in *.md; do fn=${f##*-}; sed -i "1 s/^/${fn%.*} /" "$f"; done

  • fn=${f##*-} - truncating the longest matched sequence from the left till the last occurrence of - (for ex. abcd.md)

  • ${fn%.*} - truncating the rightmost sequence (from the end) till the 1st occurrence of .(dot) from the previous substring fn (i.e. abcd)

  • sed -i "1 s/^/${fn%.*} /" "$f" - add the needed string to the beginning of the file

RomanPerekhrest
  • 29,703
  • 3
  • 43
  • 67
  • As an alternative, if the filenames are all the same size, you can also use: `for f in *.md; do sed -i "1 s/^/${fn:11:4} /" "$f"; done` – abitmol Sep 11 '17 at 01:30
0

You need to quote the *.md in your find command, or it will be expanded to matching names when you run it. You should also never use {} in a quoted context (see e.g. Is it possible to use `find -exec sh -c` safely?).

Here's a shell loop solution:

for name in ./*.md; do
    prefix="${name%.md}"             # "./2000-01-01-abcd.md" --> "./2000-01-01-abcd"
    prefix="${prefix##*-}"           # "./2000-01-01-abcd"    --> "abcd"

    { echo "$prefix"; cat "$name"; } >"$name".tmp && mv "$name".tmp "$name"
done

The same thing with find:

find . -type f -maxdepth 1 -name "*.md" \
    -exec sh -c 'p="${1%.md}";p="${p##*-}";{ echo "$p";cat "$1"; }>"$1".tmp && mv "$1".tmp "$1"' sh {} ';'
Kusalananda
  • 320,670
  • 36
  • 633
  • 936
  • `$prefix` must be prepended to the file content, not to the file name. – xhienne Sep 10 '17 at 17:27
  • @xhienne Well, that wasn't really clear from the question, but ok. Fixed it. – Kusalananda Sep 10 '17 at 17:30
  • Agreed that `find -exec "sh -c ... {} ..."` is bad practice but apparently, from OP's comment in their own answer, this was a prerequisite. BTW, like in your answer, `*.md` needs not be quoted. – xhienne Sep 10 '17 at 17:39
0

I found that this is the closest to what I was looking for. The idea of a tmp buffer solves the purpose. Other solutions hint towards for loops which in my opinion is already taken care by find -exec combination.

https://unix.stackexchange.com/a/197400/119007

find ./ -name '*.md' -exec sh -c "echo '{}' | sed 's/.md//' | sed 's/2000-01-01-//' > tmp && cat {} >> tmp && mv tmp {}" \;
infoclogged
  • 919
  • 2
  • 11
  • 24
  • See also: https://unix.stackexchange.com/questions/156008/is-it-possible-to-use-find-exec-sh-c-safely – Kusalananda Sep 10 '17 at 17:21
  • That seems quite convoluted. [RomanPerekhrest's answer](https://unix.stackexchange.com/a/391452/203203) below seems to do the same and is much simpler. – xhienne Sep 10 '17 at 17:25
  • @xhienne : it might be simpler, but the simplicity was not important, instead, how to do with find -exec as asked in the question itself. – infoclogged Sep 10 '17 at 17:28