$ ls *

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.

  • 1
    What do you want the filenames to be in the end? – Kusalananda Sep 10 '17 at 15:34

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 1:30

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.


find ./ -name '*.md' -exec sh -c "echo '{}' | sed 's/.md//' | sed 's/2000-01-01-//' > tmp && cat {} >> tmp && mv tmp {}" \;

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"

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 {} ';'
  • $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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.