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,793
  • 2
  • 53
  • 69

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

  • 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
  • 333,661
  • $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 {}" \;